I'm using angular mat table to display an array of data like below with simple sorting. The final column is a column of buttons. I'd like to have distinct buttons in each row that route to a different component.
Array as a table
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef="let device"> {{device.name}} </td>
</ng-container>
<!-- SerialNo Column -->
<ng-container matColumnDef="serialNo">
<th mat-header-cell *matHeaderCellDef > SerialNo </th>
<td mat-cell *matCellDef="let device"> {{device.serialNo}} </td>
</ng-container>
<!-- Button Column -->
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef > Actions </th>
<td mat-cell *matCellDef="let row" >
<button mat-button routerLinkActive="list-item-active" routerLink="/device1" >View</button>
</td>
my component.ts is like this.
export interface Devices {
name: string;
position: number;
serialNo: number;
}
//An Array of device1
const DEVICES: Devices[] = [
{position: 1, name: 'Device 1', serialNo: 135421},
{position: 2, name: 'Device 2', serialNo: 125240},
{position: 3, name: 'Device 3', serialNo: 124350},
{position: 4, name: 'Device 4', serialNo: 124500},
{position: 5, name: 'Device 5', serialNo: 145620},
];
displayedColumns: string[] = ['position', 'name', 'serialNo', 'actions'];
dataSource = new MatTableDataSource(DEVICES);
#ViewChild(MatSort) sort: MatSort;
ngAfterViewInit() {
this.dataSource.sort = this.sort;
}
How would I go about adding distinct buttons in each row that use routerLink to route to different components.
Do you want to redirect each link to a different angular component or do you want to redirect each link to the same angular component (for example, a device detail component), but with different url and device information (like redirecting to '/device/1', 'device/2' etc..)?
If the latter is the case, suppose you want to redirect each device to an angular route '/device-detail/:id', where id is the identification of the device. For simplicity, suppose id is the serialNo. So you just need to change the button declaration. Substitute routerLink="/device1" for [routerLink]="['/device-detail', device.serialNo]" (I also changed *matCellDef="let row" to *matCellDef="let device"):
<td mat-cell *matCellDef="let device" >
<button mat-button routerLinkActive="list-item-active" [routerLink]="['/device-detail', device.serialNo]" >View</button>
</td>
Related
Just want to ask if is it possible to search an item in an array of objects and use it as datasource for my angular table? Can you share the syntax please?
Basically, i have an array of objects consisting of Id and its json file. Populate its data. Look for an item that matches the it, and use it as datasource in a ngfor grid.
I have the following code, but it returns compilation error.
Thanks
ts file
jsonData: Array<{ id: string, json: object }> = [];
ngOnInit(): void {
let json= [
{
"Id": "1",
"Col1": "val11",
"Col2": "val12
},
{
"Id": "2",
"Col1": "val21",
"Col2": "val22
}
]
this.jsonData.push({ id: "100", json: json });
}
html file
<ng-container *ngFor="let row of this.jsonData.find(e => e.id === "101").json;let i=row.Id">
row.Col1 //etc..
</ng-container>
I Have used a different approach check if this helps you out . I am filtering data from the constructer itself (ts file)
here is the code link https://stackblitz.com/edit/angular-wn7vwb?file=app%2Ftable-basic-example.ts
HTML
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<!-- 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>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
ts
import { Component } from '#angular/core';
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 = ['position', 'name', 'weight', 'symbol'];
dataSource = ELEMENT_DATA;
constructor() {
this.dataSource = this.dataSource.filter((res) => res.name == 'Helium');
}
}
export interface PeriodicElement {
name: string;
position: number;
weight: number;
symbol: string;
}
I am trying to implement mat table , problem is its sorting and paginator is not working , i have gone through all questions related same but unable to fix it . If I am getting 10 records it shows only first five and if i change some code and try then it either shows all 10 , but not working as expected
HTML File
<div id="div1"
[hidden]="!( div1===1 && div2===0 && div3===0)">
<table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="cola">
<th mat-header-cell *matHeaderCellDef mat-sort-header> col a </th>
<td mat-cell *matCellDef="let row"> {{row.colvala}} </td>
</ng-container>
<ng-container matColumnDef="colb">
<th class="headerCell w-17" mat-header-cell *matHeaderCellDef>colb</th>
<td mat-cell *matCellDef="let row"> {{row.colvalb}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="4">No data matching the filter "{{input.value}}"</td>
</tr>
</table>
<mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
</div>
My TS file
export class mycomponent implements OnInit {
#ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
#ViewChild(MatSort, { static: true }) sort: MatSort;
constructor(private _servcall: AppService) {
}
ngOnInit() {
this._servcall.getdatafromapi().subscribe(result => {
this.resultdata = result;
this.displayedColumns = ['col1','col2']
this.dataSource = new MatTableDataSource(this.resultdata);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
})
}
}
like this one div I have more 8 div and all have mat able in it , and every mat table paginator and sorting having issue like this
it's render timing issue, wrap your paginate and sort logic in a setTimeOut ()
ngOnInit() {
this._servcall.getdatafromapi().subscribe(result => {
this.resultdata = result;
this.displayedColumns = ['col1','col2']
this.dataSource = new MatTableDataSource(this.resultdata);
setTimeout(
() => {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
});
}
})
for more details refer to
MatSort and MatPaginator does not work without setTimeOut
Check this, this worked like a charm for me
you got to set the MatTableDataSource to some initial value
//create data source
this.myDataSource = new MatTableDataSource(initialData);
// update data in data source when available
this.streamOfDataUpdates.subscribe(newData => this.myDataSource.data = newData)
ref: https://github.com/angular/components/issues/8381#issuecomment-344020159
I am having some issues trying to populate a table with two arrays. I am trying to achieve the following output:
I have an array called students and within each student object, I have a courses array. I am trying to populate my table using ng-repeat to show all courses against each student.
Not all data is given within each course, meaning that if a student hasn't started a course then it won't appear in the courses array. Also, if a student hasn't finished a course there will be no date completed given.
So my array looks like so:
$scope.students = [
{
Id: 1,
Name: 'Joe Blogs',
Courses: [
{
Title: 'Course 1',
Grade: 87,
Completed: true,
DateCompleted: '2018-01-01'
},
{
Title: 'Course 2',
Grade: 2,
Completed: false
}
]
},
{
Id: 2,
Name: 'Peter Smith',
Courses: [
{
Title: 'Course 1',
Grade: 100,
Completed: true,
DateCompleted: '2018-01-01'
},
{
Title: 'Course 2',
Grade: 95,
Completed: true,
DateCompleted: '2018-01-01'
},
{
Title: 'Course 3',
Grade: 10,
Completed: false
}
]
},
{
Id: 3,
Name: 'Joanne Someone',
Courses: [
{
Title: 'Course 3',
Grade: 55,
Completed: false,
}
]
}
]
So far my code snippet looks like this:
<table class="table table-hover" width="100%">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Course</th>
<th>Grade</th>
<th>Completed</th>
<th>Date Completed</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="student in students">
<td>{{ student.Id }}</td>
<td>{{ student.Name }}</td>
<td>
<!-- Can't figure this bit out -->
</td>
</tr>
</tbody>
</table>
But I am stuck on how to get multiple courses to show against each student. Also I have found that by using ng-repeat, if a value isn't in the object (e.g. Date Completed) then that field will not show and pushes everything up and out of alignment.
Lastly, I will mention that I am using angular-datatables however, I am just trying to work out the concept, then I can apply this to datatables later.
You'll have to use rowspan for that purpose. And the value of that for particular Id should be of length of Courses. Then, you'll need to have ng-repeat on tbody to repeat tbody section & have ng-repeat inside on tr for repeating Courses arrays of each student. So, your table view code can be:
<table>
<thead>
<tr>
<td>Id</td>
<td>Name</td>
<td>Course</td>
<td>Grade</td>
<td>Completed</td>
<td>Date Completed</td>
</tr>
</thead>
<tbody ng-repeat="x in students">
<tr>
<td rowspan="{{x.Courses.length}}"><span>{{ x.Id }}</span></td>
<td rowspan="{{x.Courses.length}}"><span>{{ x.Name }}</span></td>
<td><span>{{x.Courses[0].Title}}</span></td>
<td><span>{{x.Courses[0].Grade}}</span></td>
<td><span>{{x.Courses[0].Completed}}</span></td>
<td><span>{{x.Courses[0].DateCompleted}}</span></td>
</tr>
<tr ng-repeat="item in x.Courses" ng-if="$index > 0">
<td><span>{{item.Title}}</span></td>
<td><span>{{item.Grade}}</span></td>
<td><span>{{item.Completed}}</span></td>
<td><span>{{item.DateCompleted}}</span></td>
</tr>
</tbody>
</table>
To avoid breaking of table code if some values are not available, just have it inside span element so it'll still load td with no value inside it.
Plunker Example
http://jsfiddle.net/ADukg/13415/
I have an object called 'orders' that contains a list of foods, filterable by type with the select box below. The select box contains the filter for the food category of the orders. I want to be able to filter out a table using angular using this select box.
$scope.orders = {
"order1": {food_name: "apple", type: 1},
"order2": {food_name: "banana", type: 1},
"order3": {food_name: "carrot", type: 2},
"order4": {food_name: "cereal", type: 3},
"order5": {food_name: "wheat", type: 3}
}
$scope.foodCategories = [{id:0,name:"All"}, {id:1,name:"Fruit"},{id:2,name:"Vegatable"}, {id:3,name:"Grains"}];
HTML:
<div ng-app = "myApp" ng-controller="foodCntrl">
Select Food Type:
<select
class="form-control" ng-model="foodCategories" ng-options="type as type.name for type in foodCategories">
</select>
<table class="table">
<thead>
<tr>
<th>Food Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="f in orders | filter:foodCategories.id">
<td>{{f.food_name}}</td>
</tr>
</tbody>
</table>
</div>
I am getting the angular console error:
Error: filter:notarray
Not an array when using filter:foodCategories on the table ng-repeat.
How can I fix this?
Just add a filter for the property "type" in your orders array, and for the "foodCategories" make the id for the "All" category empty string as so {id:"",name:"All"}.
<table class="table">
<thead>
<tr>
<th>Food Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="f in orders | filter:{type: doorTypeSelect.id}">
<td>{{f.food_name}}</td>
</tr>
Here is a working plunkr: http://plnkr.co/edit/4V0i1AIGRovnOUSp7eom?p=preview
I am using ngTable to show data in table with pagination.
But Now I want to add sorting on each column.
Does any on have an idea about it?
have a look at ngTable documentation - here and example here
function demoController(NgTableParams, simpleList) {
this.tableParams = new NgTableParams({
// initial sort order
sorting: { name: "asc" }
}, {
dataset: simpleList
});
}
Prefer this
Example
<table ng-table="vm.tableParams" class="table" show-filter="true">
<tr ng-repeat="user in $data">
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
{{user.name}}</td>
<td title="'Age'" filter="{ age: 'number'}" sortable="'age'">
{{user.age}}</td>
</tr>
</table>
you have to create filter like this.
Likewise you can add serch object name into each column