PrimeNG table is not taking the fixed width in Angular - html

I am trying to fix the width of the first column in the primeNG table but somehow it is overriding my CSS even though it is showing while inspecting the element.
Basically, I am looking for CSS in which by changing the tab the first column of the table will have a fixed width no matter what is the size of all columns.
I have tried following way by defining fixed width for the first child but it is taking based width:100%.
In the above image, you can see the size is coming as 368 even though it is 100px defined.
Same when I change the tab, the width is coming as 920 even 100px is fixed.
Is there any way I can define fixed-width 100px with having table width:100% as I don't want to break responsiveness?
Below is reproducible example for reference:
https://stackblitz.com/edit/primeng-tablescroll-demo-wtpbny

In primeng 12 they removed colgroup template so if you are using colgroup over the application need to remove because custom width is not working for column if you are using scrollable check migration guide.
link:https://github.com/primefaces/primeng/wiki/Migration-Guide
solution:
you need to add same width for both tags <th [style]="'width':'100px'"> and <td [style]="'width':'100px'">
if you are using dynamic columns then add one more property width like below
[{ header: "Name", field: "name", width: '100px' }] // column object array object
<p-table [value]="data" [columns]="ColumnObjectArray">
<ng-template pTemplate="header" let-columns>
<tr>
<th *ngFor="let col of columns; let idx=index;" class=""
[style]="'width':col.width">{{col.header}}</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-data let-columns="columns">
<tr>
<td *ngFor="let col of columns" [style]="'width':col.width">
{{data[col.field]}}
</td>
</tr>
</ng-template>
</p-table>
try this one you will definitely get the responsive width to table and also you will get the custom column and header width

I've the solution required in one of my projects.
You should perform these steps:
Set a width for your desired columns
Set the horizontal scroll as per primeng documentation, in Horizontal Scroll section:
Horizontal Scroll:
In horizontal scrolling, it is required to give fixed widths to columns. In general when customizing the column widths of scrollable tables, use colgroup as below to avoid misalignment issues as it will apply both the header, body and footer sections which are different separate elements internally.
Here is a live example including a fixed size only for first column and a responsive table.
This is the only solution (setting a fixed size for your table) because if you set the width to 100% in a mobile device, probably not all columns will be displayed or will be overlapped, breaking responsiveness.

I think the problem is just that your selector for the th element is slightly incorrect. You have:
::ng-deep .p-datatable .p-datatable-tbody > tr > th:nth-child(1) {
but you just need to use .p-datatable-thead instead of .p-datatable-tbody:
::ng-deep .p-datatable .p-datatable-thead > tr > th:nth-child(1) {

This should fix. Removing fixed with for all th elements.
Add this to your style.css
.p-datatable .p-datatable-thead > tr > th {
width: inherit !important;
}

Related

PrimeNG TurboTable with custom width does not work properly

I am trying to use a PrimeNG turbotable with custom size (500px) and I expected the columns width to be set automatically however it does not work. I get a horizontal scrollbar and the total width seems to be fixed at 767 pixels. If I try to set the column width manually it gets ignored. If i don't set the table width and I try to put it inside a DIV that is 500px wide I still get the same result (horizontal scrollbar).
Below is the (very simple) code:
<p-table #dt [value]="statusChangesData" [paginator]="true" [alwaysShowPaginator]="false" [rows]="2" [style]="{'width':'500px'}">
<ng-template pTemplate="caption" >
<div class="tableCaption">
<span translate>Status changes</span>
</div>
</ng-template>
<ng-template pTemplate="emptymessage">
<tr>
<td [attr.colspan]="3">
<span translate>There are no data into the table</span>
</td>
</tr>
</ng-template>
<ng-template pTemplate="header">
<tr>
<th style="width:200px" [pSortableColumn]="'date'"><span translate>Date</span><p-sortIcon [field]="'date'"></p-sortIcon></th>
<th style="width:200px" [pSortableColumn]="'status'"><span translate>Status</span><p-sortIcon [field]="'status'"></p-sortIcon></th>
<th style="width:100px" [pSortableColumn]="'userId'"><span translate>User ID</span><p-sortIcon [field]="'userId'"></p-sortIcon></th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-col>
<tr>
<td>{{col.date}}</td>
<td>{{col.status}}</td>
<td>{{col.userId}}</td>
</tr>
</ng-template>
</p-table>
and this is what it looks like:
Turbo Table
As you can see both the header and the paginator respect the width I set (500px) but the body of the table does not.
I have tried every suggestion I can find in stack overflow including setting
the style like this: [style]="{'width':'200px'} or using [autoLayout]="true" but nothing seems to work. I am using primeNG 7.0.0.
PS. I don't really care to set each column width manually. I just don't want the horizontal scrollbar.
In case someone has a similar problem try setting the min-width of the table to 0:
::ng-deep .ui-table .ui-table-wrapper table {
min-width: 0px;
}
I copied your code from above and pasted it in a new Stackblitz project to test it. I even specified the 7.0.0 version of PrimeNG specifically, to make sure there are not any issues with different versions. (I have found that to be the case when I have used PrimeNG.) I also made up some data to show.
I am not seeing the issues you are talking about. Here is what my resulting grid looks like (ignore the fact that Stackblitz is not finding the primeicons.)
It is staying perfectly 500px wide and all columns are obeying the fixed widths you specified in the header row (<th> tags.) When I removed the fixed widths you provided in your <th> tags, all of the columns are auto-adjusting and fitting within the 500px table.
I have this table in its own component and it is not wrapped in a <div> or any other tags. You can check it out on the Stackblitz link I provided above.
I wonder if there is something about the rest of the page this is contained in that is causing the problem?

offsetWidth different when inside DIV vs TD

I am using primeng with angular, However, it feels like my problem is with html/css.
I have found out how to present my ui the way I would like with the datatable component. However, when I leverage the datatable component inside the rowexpansion feature my column widths are not adhered to.
You will see that in the below table inside a table the column width is 100px. The parent table has it correctly set to 100px.
Here is the entry code entry
Here is where the width of the columns are set
Specifically the code that I debugged is below
for(let i = 0; i < columns.length; i++) {
columns[i].style.width = columns[i].offsetWidth + 'px';
}
The offsetWidth is different for the parent then the child even though I am setting the style the same way for both tables.
My conclusion thus far is that offsetWidth is calculated differently when my table is inside a div vs inside of a td.
I looked at the default css for each HTML element and tried to make them match. However, it must be displayed as a table-cell because it requires the colspan attribute otherwise the row won't span the table as intended.
I have looked at a number of websites to determine how offsetWidth is calculated but nothing has stood out to me. So I am going to the SO community to see if there is a bug in the browser (Chrome) or if there is a css property I can use to make it behave the same way.
The offsetWidth and offsetHeight returns the element's layout width and height.
It includs the width of the visible content, scrollbars (if any), padding, and border.
Read more here...
Table has a cellspacing property which is used by the TD tag. This cellspacing is not considered in offsetWidth or offsetHeight. Aside div tag has no cellspacing property.
Below example will clear/solve your problem.
var a = document.getElementById('div');
var b = document.getElementById('tda');
var log = document.getElementById('log');
//Border+Padding+ClientWidth
log.insertAdjacentHTML("beforeend","Div offset: "+a.offsetWidth);
log.insertAdjacentHTML("beforeend","<br />Table offset: "+b.offsetWidth);
log.insertAdjacentHTML("beforeend","<br />Table Tbody offset: "+b.children[0].offsetWidth);
log.insertAdjacentHTML("beforeend","<br />Table TR offset: "+b.children[0].children[0].offsetWidth);
//Border+Padding+ClientWidth, Except Cell spacing
log.insertAdjacentHTML("beforeend","<br />Table TD offset: "+ b.children[0].children[0].children[0].offsetWidth);
#tda {width:400px}
#div{width:100px;border: 1px solid red}
<div id="div">DIV</div>
<table id="tda" border="1" cellpadding="5" cellspacing="6">
<tr>
<td>TD</td>
<td>TD</td>
</tr>
</table>
<pre id="log"></pre>
So I still don't know why I get different results between div and td.
However, looking here I was able to find the width property that does the same thing as auto, in my case, called max-content. When I set this CSS width property value on my table, I get the same result in the child as in the parent. See screenshot below:
Again I don't know why auto gives me different results for the child and the parent table but I found a workaround.
In case someone else is still interested, the best information I found for this so far was here.

How do I specify that a html cell should have the minimum width it needs to display all of its content

In the following example,
<table style="width: 100%;"><tr>
<td>First Cell</td>
<td>Second Cell</td>
</tr></table>
How do I set the widths so that the first cell/column is exactly as wide as it needs to be to show the content of the first cell and let the second cell fill the rest of the width of the table?
I'm using a GWT HorizontalPanel to do this, so if there's either a html, css or gwt trick. Please let me know.
Thank you
Assuming that “as wide as it needs to be to show the content of the first cell” refers to width needs to show the content without line breaks, you can use something like this:
<table width=681 border><tr>
<td nowrap>First Cell</td>
<td width="100%">Second Cell</td>
</tr></table>
There is no guarantee that this will keep working, since requiring a cell to be 100% wide, yet include another cell with nonzero width, is an impossible requirement. But browsers currently do what seems to be closest to the requirement.
You could achieve the layout you’re aiming for without tables, as explained in this question:
xHTML/CSS: How to make inner div get 100% width minus another div width
HTML
<div class="two-columns">
<div class="fit-to-contents">First Cell</div>
<div class="fill-remaining-space">Second Cell</div>
</div>
CSS
.two-columns {
overflow: hidden;/* Contains descendant floats */
}
.two-columns .fit-to-contents {
float: left;
background: #ffd;
}
.two-columns .fill-remaining-space {
overflow: hidden;
background: #fdf;
}
I’m not sure if that would actually be appropriate for your use-case though, I’d need to see the context.
Tables take care of themselves in HTML. There is no need to force any cell to be any particular size.
What is it you're really trying to do?
What version of HTML are you using? (Hint: Upgrade to HTML5 and CSS!)
Just don't specify any widths at all (neither on the table nor on the cells) and use white-space: nowrap on your table cells.
Put a style of width:1px on the first cell. The table will then make the first cell as narrow as possible, without causing overflow.
Since "as narrow as possible" is the width of the word "First" in this case, you may want to throw in a white-space:nowrap too, otherwise it will display "First" and "Cell" on two lines.
Jsfiddle

Tables: How to achieve “normal” td widths, but 100% table width?

On our site we have tables containing data. We like the column widths we get with a normal table, but we like the border-bottom of tds to stretch the entire width of the page like we get with CSS: table { width:100% }, as can be seen on a demo table widths page, which renders like this:
Is it possible to achieve the same column widths as with a normal (non-width-100%) table in a table where the border-bottom stretches the entire width?
And no, td { white-space: nowrap } in combination with an extra width: 100% td (see the link above) is not good, as sometimes the tds are long and so we want the tds to wrap exactly like in a normal table.
We need a solution that works in at least IE6-8 + FF.
Btw, is there a better way (tm) of showing HTML snippets than linking to an external page? I can show just source, but having HTML rendered too is very illustrative.
This was originally posted on Webmasters, but following a suggestion there, I now (re)post it here.
I finally figured it out.
My first few attempts dealt with floating <td>s and <tr>s, but apparently I was on the right track but had the wrong element.
I think what you want to do is to float the <tbody>. The <table> will still be 100% width, so it will stretch the whole width of the page, but the <tbody> inside of it will act as a container for everything else, and floating it will release it from the shackles of the size of its <table> container width.
The downside of this is that you won't be able to use <thead> or <tfoot> elements, because you will no longer have any way to align them with the <tbody> content.
Try this out:
table {
width: 100%;
border: 1px #000 solid;
}
tbody {
float: left;
}
td {
border: 1px #000 solid;
}
You can use the new CSS properties min-width and max-width to bound the columns sizes without setting them explicitly.
To get a proportional version of what would be rendered when the table's width is not specified, I think you'd have to let it render normally (remove your table width setting) and then use javascript to read the column widths and resize.
Pulled this example of using jQuery to syncronize the column widths of two tables from another question:
$("#t1").width($("#t2").width());
$("#t1 tr td").each(function (i){
$(this).width($($("#t2 tr:first td")[i]).width());
})
Should be a pretty good starting point for scaling your column widths.
This is pretty ugly and not exactly what you asked for, but it works in Firefox and appears to get the same gist...
<html>
<head>
<style type="text/css">
td{background-color:blue;}
div{border:1px solid red;position:absolute;width:100%;}
</style>
</head>
<body>
<table>
<tr>
<td>asdf<div></div></td><td>hello blah blah</td>
</tr>
<tr>
<td>lorem ipsum dolor si amet</td><td>testing</td>
</tr>
</body>
</html>
I was looking for a similar answer to this question, however I don't understand what you mean by
And no, td { white-space: nowrap } in combination with an extra width: 100% td (see the link above) is not good, as sometimes the tds are long and so we want the tds to wrap exactly like in a normal table.
But anyway, I found a solution to my problem. Not sure if it can be used here, but it solved my problem. Maybe it can be helpful to others.
I didn't add in another td. I just applied 100% to every last td with content.
So I could add a class to every last td to do that, or I could use the last-child selector to do it for me.
Something like:
table
{
width:auto;
}
table tr td:last-child
{
width:100%;
}

Keeping a certain row or column in an HTML table fixed

I have huge amounts of data populating an HTML <table> having more than 200 rows and 200 columns.
However, when I scroll the page horizontally or vertically to view the data, the header columns (like th for instance) go beyond the page.
How can I scroll through the table and still keep the top row and leftmost column fixed so that I will always know what data I'm seeing.
Here is a good solution: http://www.imaputz.com/cssStuff/bigFourVersion.html
Although implementing a JavaScript/jQuery solutions opens a lot more doors.
See this SO post for more info: HTML table with fixed headers?
You can use jQuery or you can try to mix the solution below:
header: http://fixed-header-using-jquery.blogspot.com/2009/05/scrollable-table-with-fixed-header-and.html
header and first column too but still in beta:
http://fixedheadertable.mmalek.com
Just the first column fixed:
http://www.java2s.com/Code/HTMLCSS/Table-Style/Fixedtablefirstcolumn.htm
Use simple solutions when they exist. :)
You can use a tbody and give it either fixed height or max-height and overflow: auto;:
CSS:
tbody {
max-height: 500px;
max-width: 100%;
overflow: auto;
}
And HTML like so:
<table>
<thead>
<tr><th>headers</th></tr>
</thead>
<tbody>
<tr><td>body</td></tr>
</tbody>
<tfoot>
<tr><td>footers</td></tr>
</tfoot>
</table>