Angular material table - column width by string length - css

In my app I have a bunch of different material tables.
I want to find some way to automatically set column width.
I know, I can set this directly in CSS like this and I try this
.mat-column-position {
flex: 0 0 10%;
}
.mat-column-name {
flex: 0 0 25%;
}
.mat-column-weight {
flex: 0 0 25%;
}
.mat-column-symbol {
flex: 0 0 25%;
}
But in this way, I need to manually set the width for every table.
I also try dynamically set CSS with SCSS
#mixin mat-table-columns($columns)
{
.mat-column-
{
#each $colName, $props in $columns {
$width: map-get($props, 'width');
&#{$colName}
{
flex: $width;
min-width: $width;
#if map-has-key($props, 'color')
{
color: map-get($props, 'color');
}
}
}
}
}
#include mat-table-columns((
orderid: (width: 6rem, color: gray),
date: (width: 9rem),
items: (width: 20rem)
));
But in all of these ideas, I need to manually set the width.
I try to find, is there any way to automatically set the width relative to the string with the longest length
| abc | abcdefg | abcdefgh |
| abcde | abc | abc |
| ab | abcdef | abc |
Here is stackblitz for example. Thnx

I would recommend using native table elements, this way your cells will auto resize and you should never have to worry about setting them manually.
<ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef> No. </th>
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
</ng-container>
https://stackblitz.com/edit/angular-8kyrsp-gnhbfd?file=src%2Fapp%2Ftable-flex-basic-example.css

As robbieAreBest suggested, the native table element will resize.
What I didn't know is that all that needs to be done is this:
<table mat-table>
your table
</table>
instead of (old way)
<mat-table>
your table
</mat-table>
See docs for more info

Related

table header background color change dynamically - Angular material

I have followed this example to implement the angular material table.
https://stackblitz.com/angular/jejeknenmgr?file=src%2Fapp%2Ftable-basic-example.ts
Here I changed the heading color using the below CSS code.
.mat-header-cell {
background: red;
}
I want to pass the heading color from the component instead of the static CSS way. Is there any way to change the heading color dynamically?
One of approach is to use Css Var and change variable value programatically in component.
Css
.mat-header-cell {
background: var(--background-color)
}
Component
export class AppComponent {
constructor()
changeColor() {
// set new color here
document.documentElement.style.setProperty(`--background-color`, 'red');
}
}
So when you change variable in css, browser will change value in .mat-header-cell class
Another approach is to use inline style background-color attribute on each mat-header-cell item.
In html
<ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef [style.background-color]="color"> No. </th>
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
</ng-container>
In component
export class TableBasicExample {
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
dataSource = ELEMENT_DATA;
color = 'green'
changeColor() {
this.color = 'red';
}
}
Example

How to style individual rows of Angular Material Data Table?

I want to style the individual rows of the data table based on some json values.
For example if a particular row has a temperature value of >30, I have to color that row as red. If it is between 30 to 50, the color should be green. Else the color should be green.
As of now I am only able to target the even rows or odd rows using:
tr:nth-child(even)/tr:nth-child(odd).
You should be able to add CSS classes directly to the row elements:
<tr mat-row *matRowDef="let row; columns: displayedColumns;"
class="temperature-row"
[ngClass]="{'high': row.temperature > 30}">
</tr>
Then you can use the classes to style the rows as desired:
.temperature-row {
background-color: green;
}
.temperature-row.high {
background-color: red;
}
I like to style table rows using this pattern:
<tr *ngFor="let temperature of temperatures"
[ngClass]="{'green' : temperature.value == 10, 'orange' : temperature.value == 20, 'red' : temperature.value == 30}">
<td>{{temperature.value}}</td>
</tr>
And I define my colours, or any other styles, for those rows in CSS like this:
.red{
color: red;
}
.orange{
color: orange;
}
.green{
color: green;
}

scss for loop renders percentage wierd

I'm trying to make a responsive design that flips from horizontal to vertical depending on the screen width and I need all the widths in percentage defined in css because I cannot use JavaScript.
The app is based on Middleman (a ruby gem) and I use scss as the css processor/renderer.
For this in scss:
#for $i from 0 through 100 {
.width-percentage-#{$i} {
width : #{percentage($i/100)};
}
}
It gets this in css :
...
.width-percentage-27 {
width: 27%
}
.width-percentage-28 {
width: 28.0%
}
.width-percentage-29 {
width: 29.0%
}
.width-percentage-30 {
width: 30%
}
...
.width-percentage-53 {
width: 53%
}
.width-percentage-54 {
width: 54%
}
.width-percentage-55 {
width: 55.0%
}
.width-percentage-56 {
width: 56.0%
}
.width-percentage-57 {
width: 57.0%
}
.width-percentage-58 {
width: 58.0%
}
.width-percentage-59 {
width: 59%
}
...
Now notice the problem ... for 28, 29,55, 56, 57, 58 there is a .0 in the value.
The browsers I'm targeting are handling this fine. But how does scss processor renders somehow different value types (int and floats) in the same loop ?
Strange indeed you could solve this issue by using round or ceil
#for $i from 0 through 100 {
.width-percentage-#{$i} {
width : round(percentage($i/100));
}
}
An example: http://sassmeister.com/gist/2c6f6b7cd825b16e423a
You only need to add % symbol to 100 to make the operation work.
#for $i from 1 through 100 {
.width-percentage-#{$i} {
width : #{100% / $i};
}
}

Mediawiki table: "efficiently" applying different alignment for different column

How can I efficiently center-align some columns while left-align others?
I want to do something like this.
-------------------------
| A |B |
-------------------------
| C |D |
-------------------------
This code makes all columns centered.
{| class="wikitable" style="text-align: center;"
|-
! Header 1
! Header 2
|-
| A
| B
|-
| C
| D
|}
And I know the following code does what I want.
{| class="wikitable"
|-
! Header 1
! Header 2
|-
| style="text-align: center;" | A
| B
|-
| style="text-align: center;" | C
| D
|}
But since I need to make a quite lenghty table, this is tedious.
Is there any code that will center-align only the 1st column using a very simple one line of code?
The accepted answer, while correct, can be tedious to implement generally, as you need to create a distinct CSS class for every combination of column position and text alignment that you need.
An alternative approach for one-offs is to embed CSS directly into the wiki page. On wikis that are only edited by trusted users, you can enable $wgRawHtml. On others, you can use an extension such as Extension:CSS. If you have multiple tables, you can restrict the styling to each table by using #id selectors.
<html> <!-- assumes $wgRawHtml = true; safer alternatives exist -->
<style>
table#accounts tr td:nth-child(3),
table#accounts tr td:nth-child(4)
{
text-align: right;
}
</style>
</html>
{| class="wikitable" id="accounts"
! Account Number !! Account Name !! Source Balance !! Target Balance
|-
| 1234 || UK Savings || 402.00 || 323.21
|-
| 5432 || Car Fund || 12,943.00 || 23,433.21
|-
| 6789 || Other Expenses || 4.21 || 6.21
|}
Edit: On second thoughts, going with a global approach does result in cleaner syntax within the wiki pages, especially if you have many tables with columns to align. I've created CSS classes for each alignment in the MediaWiki:Common.css page:
table.col-1-center td:nth-child(1) { text-align: center; }
table.col-2-center td:nth-child(2) { text-align: center; }
table.col-3-center td:nth-child(3) { text-align: center; }
table.col-4-center td:nth-child(4) { text-align: center; }
table.col-5-center td:nth-child(5) { text-align: center; }
table.col-6-center td:nth-child(6) { text-align: center; }
table.col-7-center td:nth-child(7) { text-align: center; }
table.col-8-center td:nth-child(8) { text-align: center; }
table.col-9-center td:nth-child(9) { text-align: center; }
table.col-1-right td:nth-child(1) { text-align: right; }
table.col-2-right td:nth-child(2) { text-align: right; }
table.col-3-right td:nth-child(3) { text-align: right; }
table.col-4-right td:nth-child(4) { text-align: right; }
table.col-5-right td:nth-child(5) { text-align: right; }
table.col-6-right td:nth-child(6) { text-align: right; }
table.col-7-right td:nth-child(7) { text-align: right; }
table.col-8-right td:nth-child(8) { text-align: right; }
table.col-9-right td:nth-child(9) { text-align: right; }
Then, within your wiki pages, you can simply reference the CSS class:
{| class="wikitable col-3-right col-4-right"
! Account Number !! Account Name !! Source Balance !! Target Balance
|-
| 1234 || UK Savings || 402.00 || 323.21
|-
| 5432 || Car Fund || 12,943.00 || 23,433.21
|-
| 6789 || Other Expenses || 4.21 || 6.21
|}
The added advantage of this approach is that you don't need to enable $wgRawHtml or install extensions.
Unless you disabled it in LocalSettings.php, you can use the page MediaWiki:Common.css to add extra stylesheets to all pages. Just do what you need there, using plain CSS. E.g:
.myTableClass td {
text-align: left;
}
.myTableClass td:first-child {
text-align: center;
}
...and then add that class to your tables
{| class="wikitable myTableClass"
|-
| A
| B
|-
| C
| D
|}

Table cell td with max-width showing too much white space if line breaks

I am trying to make a table as small as possible. One cell may have more content then the desired width so I set "max-width". So in some cases the content will be broken into more lines, which is fine.
However, when a line breaks in two the table cell remains at the max-width, while it could be smaller if it would adjust to the now broken content.
Many words, easy to look at: http://jsfiddle.net/G3bcB/10/
<p>Too much white space:</p>
<table>
<tr>
<td class="leftcell">long texttext overflow</td>
<td>B</td>
<td>C</td>
</tr>
</table>
<p>Upper table could have same width:</p>
<table>
<tr>
<td class="leftcell">long texttext</td>
<td>B</td>
<td>C</td>
</tr>
</table>
table { width: auto; }
td { border: 1px solid black; }
td.leftcell { max-width: 100px; }
I am not sure if this is a feature of HTML, but to me it seems wrong.
Is it possible to make the field smaller (using standard css)?
You can't do this without Javascript. Fortunately it's not too complicated. I changed the class of the first cell to leftcell1 to distinguish it from the lower table and lengthened the string for demo purposes:
<td class="leftcell1">
long texttext overflow long overflow
</td>
Here's the updated jsFiddle.
And the javascript:
var el = $('.leftcell1');
//temporarily puts the text in the cell to measure it
function getWidth(el, txt) {
el.html(txt);
return el.css('width').replace('px', '');
}
//returns the string w/ the <br /> tags in the right place
function splitString(maxWidth) {
var txtArr;
var presentTxt = '';
var futureTxt = '';
var finalTxt = '';
//split the words up if longer than the max width
if (getWidth(el, el.html()) >= maxWidth) {
txtArr = el.html().split(' ');
//loop through the words and add them together
for (var i in txtArr) {
futureTxt += txtArr[i] + ' ';
//check if the string is longer than the max width
if (getWidth(el, futureTxt) > maxWidth) {
//It is. Add it to the final string with a <br />
//and chop off the trailing space
finalTxt += presentTxt.substring(0, presentTxt.length - 1) + '<br />';
futureTxt = presentTxt = txtArr[i] + ' ';
} else {
//it's not. Keep adding to it.
presentTxt = futureTxt;
}
}
} else {
finalTxt = el.html();
}
//if there is anything leftover in futureTxt add it to finalTxt
if (futureTxt != '') {
finalTxt += futureTxt;
}
return finalTxt;
}
el.html(splitString(100));

Resources