Consider the object below:
var item = {
id: 'some-id',
price: 12,
customer: {
id: 'fake-id',
name: 'fake-name'
}
};
We can access the customer name using "dots" or "brackets" as below:
item.customer.name
item['customer'].name
item.customer['name']
item.['customer']['name']
Question
In Javascript or Typescript, is there a way to access customer name like the following?
item['customer.name'] or item[customer.name]
Notes
In angular I created a reusable table component based on the mat-table, which includes pagination, sort filter and bunch of other functions... I use the following for the column definitions:
mytable.component.ts:
export interface MyTableCol {
id: string;
title: string;
// some other settings...
}
mypage.component.ts:
cols: MyTableCol[] = [
{id: 'price', title: 'Total Price'},
{id: 'customer.name', title: 'Customer Name' }
];
mypage.component.html:
<my-table [columns]="cols"></my-table>
mytable.component.html:
<ng-container [matColumnDef]="col.id" *ngFor="let col of columns">
<th mat-header-cell *matHeaderCellDef mat-sort-header>
{{ col.title}}
</th>
<td mat-cell *matCellDef="let element">
{{ element[col.id] }}
</td>
</ng-container>
However, for the nested properties (customer.name) this won't work. I think the reason is the line: element[col.id] converts to element['customer.id'] in case of the customer name column.
How can I resolve this?
It won't work automatically to pass a string like that to access the properties, you need to create a getter function like lodash _get and use it to find the value you need. And then write something like:
{{ _getAtr(element, col.id) }}
Related
I have a nested array of objects , so i am trying to display in table row only first 3 elements in array and after i am displaying remaining elements in array as a count (i.e +2).Now if i click on remain count i need to display all the elements in array on particular row click.
I am attaching the stack blitz URL for reference :- https://stackblitz.com/edit/primeng-chip-demo-agf8ey?file=src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.component.ts
Please help me on these issue.
Thanks in advance
try this:
<p-chip
*ngFor="let cc of slice(c); let i = index"
[label]="cc.name"
></p-chip>
in .ts file
onChip(val: any) {
this.chips[val].extand = true;
}
slice(cc: any, index: number) {
if(cc?.extand) {
return cc.values;
}
return cc.values.slice(1,3);
}
also add to every object extand: false
chips = [
{
id: 1,
values: [
{
name: 'one',
},
{
name: 'two',
},
{
name: 'three',
},
{
name: 'four',
},
{
name: 'five',
},
],
extand: false
},]
Create a template variable:
<h5>Basic</h5>
<div class="p-d-flex p-ai-center">
<table>
<tr>
<th>Id</th>
<th>Chips</th>
</tr>
<tr *ngFor="let c of chips; let val = index">
<td>{{ c.id }}</td>
<td #myCell>
<ng-container *ngIf="myCell.showAll">
<p-chip *ngFor="let cc of c.values" [label]="cc.name"></p-chip>
</ng-container>
<ng-container *ngIf="!myCell.showAll">
<p-chip
*ngFor="let cc of c.values | slice: 0:3"
[label]="cc.name"
></p-chip>
<p-chip
styleClass="chipMore"
*ngIf="c.values.length >= 3"
(click)="myCell.showAll = !myCell.showAll"
>+{{ c.values.length - 3 }}</p-chip
>
</ng-container>
</td>
</tr>
</table>
</div>
Play at edited stackblitz: https://stackblitz.com/edit/primeng-chip-demo-ykmg3t?file=src/app/app.component.html
The table <div class="cellSubText secondary-text {{cssSubCell}}" >{{cellData[subId]}}</div> from my table-multi-sort-cell-default.component.html using the cssClass from the tableOptions which is the cssSubCell: 'c-black fs-14px'
How we construct a conditional css based on my tableOptions cssSubCell
for example cssSubCell: 'c-black fs-14px' should only work if subId !== 'test'
I tried below, but the condition does not work or recognized , is my CSS condition structure and implementation correct?
cssSubCell: 'c-black fs-14px : subId !== "test"
#this CSS works but I want it to be condition
cssSubCell: 'c-black fs-14px'
#component A tableOptions
this.tableOptions = {
columns:[
{id:'name',name:'Deal Letter',subId:'dealType', subtitle:'Deal Type'},
{id:'annualRentCurrent',name:'Annual Rent (Current)', subId: 'annualRentProposed', subtitle:'Annual Rent (Proposed)'},
{id:'firmTermRemainingCurrent',name:'Firm Term Remaining (Current)', subId: 'proposedTerm', subtitle:'Firm Term Remaining(Proposed)'},
{id:'maxAvailableTerm',name:'Max Available Term (Current)' , subId:'proposedMaxAvailableTerm', subtitle: 'Max Available Term (Proposed)'},
{id:'cashContribution',name:'Cash Contribution'},
{id:'cashFlow',name:'Store Cash Flow'},
{id:'action', name: 'Actions', actions:[
{icon:'file_copy', name:'Copy', class:'primary-color' , },
{icon:'delete', name: 'Delete', class:'mat-error ml-7px'},
{icon:'forward', name: 'For Approval', class:'primary-color'}
]}
],
cssClass: {
cssCell:'',
cssSubCell: 'c-black fs-14px'
}
}
#table screenshot
enter image description here
#table-multi-sort-cell-default.component.html
<div class="{{cssCell}}">{{cellData[id]}}</div>
<div class="cellSubText secondary-text {{cssSubCell}}" >{{cellData[subId]}}</div>
#table-multi-sort.component.html
<ng-container *ngFor="let column of table.columns" [matColumnDef]="column.id">
<mat-header-cell class="table-multi-sort-header" *matHeaderCellDef [mat-multi-sort-header]="column.id">
<div>{{column.name}}</div>
<div class="sub-text">{{getColumnSubtitle(column.id)}}</div>
</mat-header-cell>
<mat-cell *matCellDef="let row" (click)="editRow(row)">
<ng-container *ngIf="column.id !== 'action'; then col; else actionCol"></ng-container>
<ng-template #col>
<app-table-multi-sort-cell-default [cellData]="row" [id]="column.id" [subId]="getColumnSubId(column.id)" [cssCell]="cssClass.cssCell" [cssSubCell]="cssClass.cssSubCell" ></app-table-multi-sort-cell-default>
</ng-template>
<ng-template #actionCol>
<app-table-multi-sort-cell-action [rowData]="row" [actions]="getActions(column.id)" (actionClickEvent)="clickTableAction($event,row)"></app-table-multi-sort-cell-action>
</ng-template>
</mat-cell>
</ng-container>
You need to use ngClass
<div class="cellSubText secondary-text" [ngClass]="{'c-black fs-14px' : subId !=='dealType'}">
{{cellData[subId]}}
</div>
API data {
id: 1,
date: "21/may/2020",
name: "Server A",
geo: "Europa",
status: "online"
}
ngOnInit {
this.col = [
{field: 'name', header: 'Server Name'},
{field: 'geo', header: 'Geography'},
{field: 'status', header: 'Status'},
{field: 'date', header: 'Date'}
]
}
I'm testing angular PrimeNG and I have an data-table, where I set the values for each table row manually, it works fine.
template
<ng-template>
<td>
<tr>
<td>{{rowData.name}}</td>
<td>{{rowData.geo}}</td>
<td>{{rowData.status}}</td>
<td>{{rowData.date | date: 'dd/MMM/yyyy'}}</td>
</tr>
<td>
<ng-template>
I updated my template to dynamically loop through the object and set the data, how can I update my loop so I can insert the pipe when I render the "date" object.
<td *ngFor="let col of column">
{{rowData[col.field]}}
</td>
The above {{rowData[col.field]}} is working, but I not sure how to inside *ngFor="let col of columns " I can update only the col.date and add pipe into it.
This is what I trying but not successful, the baove is working but not the Pipe and also if I add keyvalue the tables data is not being displayed anymore.
<td *ngFor="let col of columns | keyvalue">
<ng-container *ngIf="rowData[col.field] !== 'date'"> {{rowData[col.field]}}</ng-container>
<ng-container *ngIf="rowData[col.field] === 'date'"> {{rowData[col.field] | date: 'dd/MMM/yyyy'}}</ng-container>
</td>
Any suggestion or example I can look into?
If i understand your question right, you want to apply pipe on the birthdate field, so you can do ,
<td *ngFor="let data of object">
{{data["birthdate"] | date: 'dd/MMM/yyyy' }}
</td>
Use key value pipe like
<td *ngFor="let data of object | keyvalue">
<ng-container *ngIf="data.key !== 'birthdate'"> {{data.value}}</ng-container>
<ng-container *ngIf="data.key === 'birthdate'"> {{data.value | date: 'dd/MMM/yyyy'}}</ng-container>
</td>
I am trying to sort a table by its columns.
The problem occurs when I have to filter a result that is inside another.
I tried to access the property by bracket notation and dot notation but none gave results.
Also placing the final node in matColumnDef but it fails because there are 2 columns with the same name.
<table mat-table [dataSource]="dataSource" matSort>
<!-- Element 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>
<!-- Username Column -->
<ng-container matColumnDef="user.name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Username </th>
<td mat-cell *matCellDef="let element"> {{element.user.name}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
displayedColumns definition:
displayedColumns = ['name', 'user.name'];
There is a dataSource example:
[
{
id: 2,
name: "Testing",
user: {
id: 1,
name: "User Testing",
username: "test#example.com"
}
},
{
id: 4,
name: "Testing_2",
user: {
id: 3,
name: "User Testing 2",
username: "test2#example.com"
}
}
]
It was hard to find documentation on this, but it is possible by customizing the sortingDataAccessor of MatTableDataSource and a switch statement.
For example:
#ViewChild(MatSort) sort: MatSort;
ngOnInit() {
this.dataSource = new MatTableDataSource(yourData);
this.dataSource.sortingDataAccessor = (item, property) => {
switch(property) {
case 'project.name': return item.project.name;
default: return item[property];
}
};
this.dataSource.sort = sort;
}
Found here: Angular Material 2 DataTable Sorting with nested objects
I'm trying to pass variable in filter object to search relevant field but when I put object without passing variable like underneath it works fine:-
stock.controller.js
var vm = this;
vm.stocks = [
{
itemName:'Peanut',
labelName: 'Fortune nuts',
cost : '$4'
},
{
itemName:'Sandwich',
labelName:'Coast Food',
cost: '$10'
}
]
vm.searchOptions = {itemName:vm.search};
stock.html
<input type="text" ng-model="vm.search"/>
<tr ng-repeat="s in vm.stocks | filter:{itemName:vm.search}">
<td>{{s.itemName}}</td>
<td>{{s.labelName}}</td>
<td>{{s.cost}}</td>
</tr>
But in case when I get object from variable It won't work. Following I pass variable vm.searchOptions instead of writing it hard coded.
<tr ng-repeat="s in vm.stocks | filter:vm.searchOptions">
<td>{{s.itemName}}</td>
<td>{{s.labelName}}</td>
<td>{{s.cost}}</td>
</tr>