I have an angular component which shows a map or a primeNG table depending on a variable. This component is prepared to act as a child component and be used inside other components. The map fits on the container it is set, but the table exceeds the height of the container if it has too many rows.
I want to force the table fitting the container, It would be nice if it auto-selects the number of rows per page in the paginator depending on the space in the container, but I would also be fine with some kind of scrollbar.
I have tried the classic scrollable='true', scrollheight and that stuff, but they do not work for me.
Edit: Adding the table code:
<div><p-table #dt
[value]="listaMapa()"
[columns]="mostrarColumnas"
(sortFunction)="customSort($event)"
[customSort]="true"
[paginator]="true"
[showCurrentPageReport]="true" [rows]="10"
[scrollable]="true"
[scrollHeight]="'100%'"
currentPageReportTemplate="{first} - {last} de {totalRecords}" [rowsPerPageOptions]="[10,25,50]">
<ng-template pTemplate="header" let-columns>
<tr>
<th [pSortableColumn]="'matricula'">MatrÃcula
<p-sortIcon [field]="'matricula'"></p-sortIcon>
</th>
<th>Latitud
</th>
<th >Longitud
</th>
<th>Ubicación</th>
<th [pSortableColumn]="'zona'">Zona
<p-sortIcon [field]="'zona'" ></p-sortIcon>
</th>
<th [pSortableColumn]="'fecha'">Fecha de registro
<p-sortIcon [field]="'fecha'" ></p-sortIcon>
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-posiciones>
<tr>
<td>{{posiciones.matricula}}</td>
<td>{{posiciones.latitud}}</td>
<td>{{posiciones.longitud}}</td>
<td>{{posiciones.descripcion}}</td>
<td>{{posiciones.zona}}</td>
<td>{{posiciones.fecha}}</td>
</tr>
</ng-template>
</p-table>
</div>
The point is that I want to be able to use this table as a child component and make sure that it will not get bigger than the container component. I have added [scrollable]="true" but it does not work for [scrollHeight]="'100%'" or [scrollHeight]="'100hv'" so I have to fix the height of the table in order to make the scroll work. I have also tried style="height: 100%;"but nothing changes.
Related
I am currently using mat-table as this simple example from documentation:
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- Position Column -->
<ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef> No. </th>
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
</ng-container>
...
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
In order to be able to change the order of the rows, I then use cdk drag and drop using the cdkDrag directive on the right of mat-row and cdkDropList on the right of mat-table. I also needed to use other properties like cdkDropListSortPredicate, but I'll keep it simple to explain my problem :
I have observed several problems with events and predicates. While inspecting the html code while doing my manipulations, I saw that the placeholder was sometimes placed outside the tbody because the element attached to CdkDropList is the table and not the tbody where the rows to be reordered are located.
So, as mentioned in the topic, have you ever successfully applied the cdkDropList directive to the tbody generated by an angular table (mat-table)? Or can you think of a solution? (I tried to create my own directive that modifies the element attached to the CdkDropList but without success)
UPDATED 1: I observe these problems especially in the situation where the dragged element comes from another list. It's the placeholder that is generated outsite of tbody. So, the problem can't be resolved with CdkDropListDropped.
UPDATED 2: Here is the stackblitz link to understand my problem. In the example, one of the problems is that I don't want the placeholder to appear in the first position in the list if you go over the header. Because visually it might look like you can drop the element here.
PS : Once I have solved this problem, another difficulty for me will be to hide the placeholder based on a condition. If you drag the element to the wrong position before dragging it to the correct position, the placeholder appears in the last position. I don't want that.
The following solution will help you. You can render the table rows within the body using cdkDropList
stackblits solution
dropTable(event: CdkDragDrop<PeriodicElement[]>) {
const prevIndex = this.dataSource.findIndex(d => d === event.item.data);
moveItemInArray(this.dataSource, prevIndex, event.currentIndex);
this.table.renderRows();
}
I'm setting up a simple table at work using Angular and have come across a problem. After I froze a couple of the columns. Whenever I scroll all the way to the bottom, the frozen columns' rows are misaligned with the scrolling columns' rows. This problem only shows up when using Edge and Firefox but it's necessary to use them. However, in Chrome the rows are aligned.
I've tried applying padding and margins to the columns' elements but it doesn't seem to work. I should also mention that I'm using the primeNg data table components to set up the tables. Here's the HTML code. Colgroup is the group of columns that scroll and frozenName is the group of columns that are frozen.
<p-table [columns]="scrollableCols" [value]="data"
[scrollable]="true" [frozenColumns] = "frozenName" [frozenValue] =
"frozendata" scrollHeight="300px" frozenWidth='400px'
[style] = "{width:'1000px'}" >
<ng-template pTemplate="colgroup" let-columns>
<colgroup>
<col *ngFor="let col of columns" style="width:200px" >
</colgroup>
</ng-template>
<ng-template pTemplate="header" let-columns >
<tr>
<th *ngFor= "let col of columns" >
{{col.header}}
</th>
</tr>
</ng-template>
<ng-template pTemplate="frozenrows" let-rowData let-columns="columns">
<tr>
<td *ngFor= "let col of columns">
{{rowData[col.field]}}
</td>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowData let-columns="columns" >
<tr>
<td *ngFor= "let col of columns">
{{rowData[col.field]}}
</td>
</tr>
</ng-template>
No errors occur when applying padding and margins but they separate the rows from the header which is not what I want.
I don't think this is a problem with your code it's just that some css doesn't work in Microsoft Edge, because there is still a lot of work to do on it.
I also have the same problem with my website.
But you could try something like this:
https://www.w3schools.com/howto/howto_css_four_columns.asp
I have a mat-table and wanted to make the columns resizeable, so I stumbled across the CSS property "resize" which works perfectly well for regular HTML tables
Basic HTML:
<table id="main_table">
<tr class="header">
<td><div class="tableHeaderCellDiv">Tech Name</div></td>
<td><div class="tableHeaderCellDiv">Name</div></td>
</tr>
</table>
CSS:
.tableHeaderCellDiv { resize: horizontal; overflow:hidden;}
Which gives the headers a very nice box with which you can resize the columns.
However, when trying to bring this exactly same thing over to my mat-table, the drag-box simply didn't show up.
<table mat-table [dataSource]="items" class="mat-elevation-z8">
<ng-container [matColumnDef]="column" *ngFor="let column of displayedColumnsMAT">
<th mat-header-cell class="custom-mat-header-styling tableHeaderCellDiv" *matHeaderCellDef>{{column}}</th>
</ng-container>
<tr mat-header-row class="tableHeaderCellDiv" *matHeaderRowDef="displayedColumnsMAT; sticky: true;" ></tr><!-- for the header row -->
</table>
I've cut out the not-header-rows for both examples, as they don't matter for now.
I've also tried inserting tableHeaderCellDiv (same CSS as for the plain HTML) as a class everywhere, guessing that that is the problem.
What am I doing wrong, or could it be that that feature simply does not work at all with Mat-Tables?
[EDIT:] thanks to #KrishnaRathore I now know that my code (probably) isn't the problem but Firefox is. If you're content with Chrome check out his answer though, it works.
HOWEVER, this problem seems to be unique to Mat-Table, as there is another small plain HTML table in my project with which the resizing works fine.
use this code
Stackblitz Demo
component.scss / component.css
.tableHeaderCellDiv {
resize: horizontal;
overflow:hidden;
}
component.html
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns">
<th mat-header-cell class="custom-mat-header-styling tableHeaderCellDiv" *matHeaderCellDef>{{column}}</th>
<td mat-cell *matCellDef="let element">{{element[column]}}</td>
</ng-container>
<tr mat-header-row class="tableHeaderCellDiv" *matHeaderRowDef="displayedColumns; sticky: true;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
I have made it work (even on firefox), but I am absolutely certain that I tried this before and then it just didn't.
<th mat-header-cell class="custom-mat-header-styling" *matHeaderCellDef><div class="tableHeaderCellDiv">{{column}} </div></th>
so the trick is to have another div INSIDE the header cell, which is resizeable, and to not make the rest resizeable.
I would like to make my table header fixed (always visible). I tried this on multiple ways, creating 2 tables above each other, position-fixed, gave each column a specific width, ...
BUT I also would like to my table to be responsive, just like the bootstrap4 standards. Can't find any solution online that works for me, does anyone have any suggestions or starting points what to look for?
--- See what I tried down below ----
My basic table now:
<div style="overflow:auto; height:60vh">
<table class="table table-hover trCursor">
<thead>
<tr>
<th scope="col">#Id</th>
<th scope="col">
#Html.ActionLink("Name", "Products", new { sortOrder = ViewBag.NameSortParm }) <i class="fas fa-sort"></i>
</th>
<th scope="col">Description</th>
<th scope="col">(Internal) Product number</th>
<th scope="col">Price(s)</th>
<th scope="col">Supplier(s)</th>
<th scope="col">
#Html.ActionLink("Created", "Products", new { sortOrder = ViewBag.DateSortParm }) <i class="fas fa-sort"></i>
</th>
#*<th scope="col">Product type</th>*#
</tr>
</thead>
<tbody id="productsBody">
#Html.Partial("_Products", Model)
</tbody>
</table>
</div>
Update These are the main things I tried out:
https://codepen.io/nikhil8krishnan/pen/WvYPvv This worked amazing on a large device (pc and tablet) but I couldn't find a solution to make this mobile-friendly. There are 2 different tables above each other so you have to scroll them separately on your phone.. (horizontal)
http://www.iamramraj.com/bootstrap-fixed-table-header-using-css/?i=1
This one only worked on a large screen. Turned out they use the bootstrap classes col-xs-5 etc to give the columns a specific width, which results in a non-responsive table.
Update2 Next things that I tried:
https://mdbootstrap.com/support/jquery/fixed-header-with-scrolling-table/ This is a very pretty working table but not responsive. On a small device, the table header and body scroll differently and have different widths.
https://forums.asp.net/t/2094852.aspx?MVC+Fixed+Header+rows+for+IEnumerable+table+razor+view Same problem here, working table but not resonsive. Columns are a different width from the headers.
https://www.bootply.com/JnOYtO9xzn When I implemented this one, it wasn't even responsive to start with! The header was fixed and the body scrollable but the position wasn't right and also not responsive.
https://jsfiddle.net/dPixie/byB9d/3/ Guess what.. Same problem again, header columns are not the same width as the body columns.
0I am working on an asp.net mvc web application, and I am using a responsive web template which is based on bootstrap. Currently the layout is responsive, where the page will adapt to the screen size to a certain limit, for example if I have a table with only four columns and the user access it using a small screen then the text can still be readable. but for some views there have tables with more than 8 columns , the text inside these tables became un-readable when beginning accessed from small size screens. As follow:-
On way I am thinking to fix this issue, is to manually define hidden-xs hidden-sm classes for the columns that are less important to the users and only display the columns that are most important , when the user access the system from small or extra small screens.
I am afraid that by approach might work, but it is very handy? Can anyone advice on this please?
Thanks
my view code looks as follow:-
<table class="table table-striped table-bordered bootstrap-datatable datatable">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model=>model.SingleOrDefault().UserName)
</th>
<th>
#Html.DisplayNameFor(model=>model.SingleOrDefault().AuditAction.Name)
</th>
<th>
#Html.DisplayNameFor(model=>model.SingleOrDefault().TechnologyType.Name)
</th>
<th>
#Html.DisplayNameFor(model=>model.SingleOrDefault().Technology.Tag)
</th>
<th>
#Html.DisplayNameFor(model=>model.SingleOrDefault().DateTimeStart)
</th>
<th>
#Html.DisplayNameFor(model=>model.SingleOrDefault().DateTimeEnd)
</th>
<th>
#Html.DisplayNameFor(model=>model.SingleOrDefault().ExtraInfo)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td>
<span class="yellow b"> #item.UserName</span>
</td>
<td>
#(item.AuditAction == null ? "None" : item.AuditAction.Name)
</td>
<td>
#(item.TechnologyType == null ? "None" : item.TechnologyType.Name)
</td>
//code goes here
Before your <table> wrap it with the bootstrap class <div class="table-responsive">. This class will make it scroll-able horizontally, what I did was to then add a comment to the user to inform them that they can "swipe" the table left and right (just on mobile). This together with hiding what you don't want to show as you mentioned is the only decent option for tables.
Hope that helps