I created an Angular component which handles some common events to be used by other components. Also defined a custom type to specify the data columns. The question is how can I set the column width based on the width specified in TableColumn type?
export type TableColumn = { columnName: string; displayName: string; sort: boolean; dataType: 'string' | 'number' | 'date'; width: number };
<ng-container [matColumnDef]="column['columnName']" *ngFor="let column of dataColumns">
<ng-container *ngIf="column['sort']">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ column["displayName"] }}</th>
</ng-container>
<ng-container *ngIf="!column['sort']"
><th mat-header-cell *matHeaderCellDef>{{ column["displayName"] }}</th>
</ng-container>
<td mat-cell *matCellDef="let element">{{ element[column["columnName"]] }}</td>
</ng-container>
Related
I made an Angular Material Table and now I'm trying to implement Sort. I build the table following the documentation for version 13, but the sorting doesn't work (even though the header is clickable and the sorting arrow changes direction on click.
Here is my component:
import { Component, VERSION, ViewChild } from '#angular/core';
import { MatSort } from '#angular/material/sort';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
#ViewChild(MatSort, { static: true }) sort!: MatSort;
dataSource = [
{ value: 'One %value% none', type: 'Type is %type%', time: 1 },
{ value: 'Another %value%', type: 'This type is %type%', time: 3 },
{ value: '%value% none', type: 'The type is %type%', time: 2 },
];
displayedColumns: string[] = Object.keys(this.dataSource[0]);
name = 'Angular ' + VERSION.major;
}
And here is the html:
<p>Table works</p>
<table mat-table matSort [dataSource]="dataSource" class="mat-elevation-z8">
<!-- Value Column -->
<ng-container matColumnDef="value">
<th mat-sort-header mat-header-cell *matHeaderCellDef>Vaule</th>
<td mat-cell *matCellDef="let element">{{ element.value }}</td>
</ng-container>
<!-- Type Column -->
<ng-container matColumnDef="type">
<th mat-sort-header mat-header-cell *matHeaderCellDef>Type</th>
<td mat-cell *matCellDef="let element">{{ element.type }}</td>
</ng-container>
<!-- Time Column -->
<ng-container matColumnDef="time">
<th mat-sort-header mat-header-cell *matHeaderCellDef>Time</th>
<td mat-cell *matCellDef="let element">{{ element.time }}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
The full reproducible example can be found here:
stackblitz
ps: there are a few similar questions in SO, but I couldn't find one with this version and this specifications.
I want to be able to add a tooltip that displays when hovering over the header of a column in a mat-table.
Is there a way to do this, because it does not display when I add the mat tooltip indicator.
<table mat-table [dataSource]="marketDataSource" matSort multiTemplateDataRows class="w-100">
<!-- Status Status -->
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header matTooltip="Info about the action">
Status
</th>
<td mat-cell *matCellDef="let element">
<span>
<mat-slide-toggle color="primary"></mat-slide-toggle>
</span>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="marketDisplayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let element; columns: marketDisplayedColumns;">
</table>
import MatTooltip module on your component.ts
import { MatTooltipModule } from '#angular/material/tooltip';
I have a problem that I do not know how to solve it from my component I send an array of Resource so that another component reads it and injects it into a DataSource that is read by a mat-table. Consulted the documentation of Angular, I see that it is correct. I do not know if it's something in the html that does not allow me to see it. Can someone tell me the reason?
Thank you so much
my .ts
#Input() resources : Resource [];
public dataSource = new MatTableDataSource <Resource> ();
public ngOnInit(): void {
console.log(this.resources)
this.dataSource.data = this.resources
}
my .html
<mat-table class="resources-table" #table [dataSource]="resources" matSort [#animateStagger]="{value:'50'}" fusePerfectScrollbar>
<!-- ID Column -->
<ng-container matColumnDef="_id">
<mat-header-cell *matHeaderCellDef mat-sort-header>ID</mat-header-cell>
<mat-cell *matCellDef="let resource">
<p class="text-truncate">{{resource._id}}</p>
</mat-cell>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef mat-sort-header>{{'RESOURCE.NAME' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let resource">
<p class="text-truncate">{{resource.name}}</p>
</mat-cell>
</ng-container>
</mat-table>
console.log(this.resources) is img:
Try to set DataSource property of Mat-Table in which you assinging the data:
HTML code:
\/ <-- Here
<table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">
<!-- Position Column -->
<ng-container matColumnDef="_id">
<th mat-header-cell *matHeaderCellDef mat-sort-header> No. </th>
<td mat-cell *matCellDef="let element"> {{element._id}} </td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
TS code:
import { Component, OnInit, ViewChild } from '#angular/core';
import { MatSort, MatTableDataSource } from '#angular/material';
#Component({
selector: 'table-sorting-example',
styleUrls: ['table-sorting-example.css'],
templateUrl: 'table-sorting-example.html',
})
export class TableSortingExample implements OnInit {
displayedColumns: string[] = ['_id', 'name'];
dataSource = new MatTableDataSource([]);
#ViewChild(MatSort) sort: MatSort;
ngOnInit() {
var elements = [{ _id: 1, name: 'Paul Walker' },
{ _id: 2, name: 'Lisa' }];
this.dataSource = new MatTableDataSource(elements); // Set dataSource like this
this.dataSource.sort = this.sort; // and then assign sort
}
}
Stackblitz
I am trying to create a mat table with sub columns using Angular Material Table like the link. Is there a way to do this with angular material table? Can I create sub columns from one the columns? Please check the table from the below link
https://datatables.net/examples/basic_init/complex_header.html
Old question, but I had a similar problem and found this example. Angular Material version is 7.3.1. The complete project can be found here
table-basic-example.html
<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>
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef> Weight </th>
<td mat-cell *matCellDef="let element"> {{element.weight}} </td>
</ng-container>
<!-- Symbol Column -->
<ng-container matColumnDef="symbol">
<th mat-header-cell *matHeaderCellDef> Symbol </th>
<td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
</ng-container>
<!-- Header row first group -->
<ng-container matColumnDef="header-row-first-group">
<th mat-header-cell *matHeaderCellDef
[style.text-align]="center"
[attr.colspan]="2">
First group
</th>
</ng-container>
<!-- Header row second group -->
<ng-container matColumnDef="header-row-second-group">
<th mat-header-cell *matHeaderCellDef [attr.colspan]="2"> Second group </th>
</ng-container>
<tr mat-header-row *matHeaderRowDef="['header-row-first-group', 'header-row-second-group']"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
table-basic-example.ts
import {Component} from '#angular/core';
export interface PeriodicElement {
name: string;
position: number;
weight: number;
symbol: string;
}
const ELEMENT_DATA: PeriodicElement[] = [
{position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
{position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
{position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
{position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
{position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
{position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
{position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
{position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
{position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
];
/**
* #title Basic use of `<table mat-table>`
*/
#Component({
selector: 'table-basic-example',
styleUrls: ['table-basic-example.css'],
templateUrl: 'table-basic-example.html',
})
export class TableBasicExample {
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
dataSource = ELEMENT_DATA;
}
table-basic-example.css
table {
width: 100%;
}
th.mat-header-cell, td.mat-cell {
text-align: center;
border: 1px solid #CCC;
padding: 0 !important;
}
I wanted a multi-header data table where the 2nd header is in the 2nd row of the data table field but didn't find any solutions related to Angular Material.
2nd header having ‘Area’, ‘City’, ‘State’ will be rendered below 'Address' header, thus using attr.colspan value = 3
Also, <tr mat-header-row *matHeaderRowDef="['stub', ‘area’ , ‘city’, ‘state’]"> is added for 2nd header to work
Here is the solution I have implemented in my code using colspan attribute. Please refer to the comments mentioned in the code
<div class="mat-elevation-z8">
<table mat-table [dataSource]="dataSource">
<ng-container matColumnDef="model">
<th mat-header-cell *matHeaderCellDef class="header-font"> Model</th>
<td mat-cell *matCellDef="let element"> {{element.model}} </td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="header-font"> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<ng-container matColumnDef="address">
<th mat-header-cell [attr.colspan]="3" *matHeaderCellDef class="header-font"> Address </th>
</ng-container>
<!--2nd Header-->
<ng-container matColumnDef="stub">
<th mat-header-cell style="background-color: white; border: none;" [attr.colspan]="2" *matHeaderCellDef> </th>
<!--stub is necessary because 2nd header should not be placed below Model, Name-->
</ng-container>
<ng-container matColumnDef="area">
<th mat-header-cell class="header-font" *matHeaderCellDef> Area </th>
</ng-container>
<ng-container matColumnDef="city">
<th mat-header-cell class="header-font" *matHeaderCellDef> City </th>
</ng-container>
<ng-container matColumnDef="state">
<th mat-header-cell class="header-font" *matHeaderCellDef> State </th>
</ng-container>
<!--add 1 more ng-container for Penetration % field-->
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-header-row *matHeaderRowDef="['stub', ‘area’ , ‘city’, ‘state’]"></tr> <!--Enable this for 2nd Header-->
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
Here is my angular project configuration,
"#angular/cdk": "^5.2.0",
"#angular/common": "~5.2.6",
"#angular/compiler": "~5.2.6",
"#angular/core": "~5.2.6",
"#angular/forms": "~5.2.6",
"#angular/http": "~5.2.6",
"#angular/material": "^5.2.0"
I am using angular material to build a table of data, I am following the https://material.angular.io/components/table/examples example, the code is almost the same with the exmaple, but the table just doesn't show any thing.
Here is the code:
ts code
export class ordersComponent {
displayedColumns =['position', 'name', 'weight', 'symbol'];
//dataSource = new MatTableDataSource<PeriodicElement>(ELEMENT_DATA);
dataSource = ELEMENT_DATA;
}
export interface PeriodicElement {
name: string;
position: number;
weight: number;
symbol: string;
}
const ELEMENT_DATA : PeriodicElement[]= [
{position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
{position: 3, name: 'Li: PeriodicElement[]thium', weight: 6.941, symbol: 'Li'},
{position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'}
];
The html code is
<div class="mat-elevation-z8">
<mat-table mat-table [dataSource]="dataSource">
<ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef> No. </th>
<td mat-cell *matCellDef="let element"> </td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> </td>
</ng-container>
<ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef> Weight </th>
<td mat-cell *matCellDef="let element"> </td>
</ng-container>
<ng-container matColumnDef="symbol">
<th mat-header-cell *matHeaderCellDef> Symbol </th>
<td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</mat-table>
</div>
I have looked into the html, found the html has produced 4 exact table html elements, but why it just doens't show any data on each html element?
Don't go with complicated solution. Instead of that create a instance of "MatTableDataSource" and in MatTableDataSource having 'data' is the property so, you can directly assign the array to this.
I added a demo here stackblitz