I have this code:
<ng-container matColumnDef="Estado">
<th mat-header-cell *matHeaderCellDef>Estado</th>
<td mat-cell *matCellDef="">
<mat-checkbox *ngIf=!state mat-checked></mat-checkbox>
</td>
</ng-container>
When the condition in the *ngIf is met the checkbox appears unchecked, but I need to get it already checked, I don't know how, hope you can help me, thank you.
The mat-checkbox component has a input called 'checked'
Try something like that:
<ng-container matColumnDef="Estado">
<th mat-header-cell *matHeaderCellDef>Estado</th>
<td mat-cell *matCellDef="">
<mat-checkbox *ngIf="!state" [checked]="true"></mat-checkbox>
</td>
</ng-container>
It's always a good idea to check the API tab in the documentation of the component you are using
You need an ngModel to with a variable set to true if you want the checkbox to default in as true. Then, if you ever check/uncheck the checkbox, the current true/false value will be saved in your variable
ts
estadoFlag: boolean = true;
html
<ng-container matColumnDef="Estado">
<th mat-header-cell *matHeaderCellDef>Estado</th>
<td mat-cell *matCellDef="">
<mat-checkbox *ngIf=!state [(ngModel)]="estadoFlag"></mat-checkbox>
</td>
</ng-container>
Related
I have a variable in my ts that contains a value of 3 (array length), I want to use it in my html to increment the value of index ([0]) until the value of 3 is reached.
<table mat-table [dataSource]="dataSourceQuizOverview" matSort>
<ng-container matColumnDef="question_text">
<th class="font" mat-header-cell *matHeaderCellDef mat-sort-header>Questions</th>
<td class="font" mat-cell *matCellDef="let row">{{row.quiz_records[0].question_text}}</td>
</ng-container>
<ng-container matColumnDef="user_answers">
<th class="font" mat-header-cell *matHeaderCellDef mat-sort-header>Answer</th>
<td class="font" mat-cell *matCellDef="let row">{{row.quiz_records[0].user_answers}}</td>
</ng-container>
</table>
ts
quiz_recordsLength.length: number = 3;
You should check, NgForOf Directive. This should solve your issue.
Also, for future questions, please remember this: How much research effort is expected of stack overflow. Posting a new question should be your last resort.
I have an angular material table
(HTML)
<table mat-table
[dataSource]="dataSource" multiTemplateDataRows
class="mat-elevation-z8">
<ng-container *ngIf="{{column}}" matColumnDef="{{column}}" *ngFor="let column of displayedColumns">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let element"> {{element[column]}} </td>
</ng-container>
I want to change the styling on the element if it equals 'Missing' (e.g. {{element[column}} == Missing then change styling).
(style) (HTML)
<mat-chip *ngIf="element.status=='Missing'" style="background-color: #ec9d9d; color: red">Missing</mat-chip>
How can I do this in the HTML? I only want to do this if the displayedColumn 'status' is equal to 'Missing'.
(Typescript)
displayedColumns: string[] = [
'id',
'tradingPartnerTradingPartner',
'fileFormatFileFormat',
'status',
];
you could use the ng-class directive
in your example, using it should be something like this:
(Assuming the mat-chip would get placed into this cell I modified below)
<table mat-table [dataSource]="dataSource" multiTemplateDataRows
class="mat-elevation-z8">
<ng-container *ngIf="{{column}}" matColumnDef="{{column}}" *ngFor="let column of displayedColumns">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let element"
[ngClass]="{missing: element.status=='Missing' }"> {{element[column]}} </td>
</ng-container>
...
and don't forget to create the css for the .missing class we are referencing in the ngClass directive:
.missing {
background-color: #ec9d9d;
color: red
}
In my project i am using Angular Material's table for displaying value in table format, As per new requirement i have to perform in-line editing for last 2 column over other along with that if user click 1st column the other column get highlighted automatically and everything has to be done using Angular material
This is the last 2 column i want to perform in-line editing
> <ng-container matColumnDef="weight">
> <th mat-header-cell *matHeaderCellDef> Weight </th>
> <td mat-cell *matCellDef="let element"> {{element.weight}} </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> </table>
How i achieved is as follows :
<tbody>
<tr *ngFor="let data of dataSource">
<td >{{data.position}}</td>
<td >{{data.name}}</td>
<td *ngIf="data.position === editRowId"> <input matInput [(ngModel)]="data.weight"></td>
<td *ngIf="data.position !== editRowId" (click)="editTableRow(data.position)">{{data.weight}}</td>
<td *ngIf="data.position === editRowId"> <input matInput [(ngModel)]="data.symbol"></td>
<td *ngIf="data.position !== editRowId" (click)="editTableRow(data.position)">{{data.symbol}}</td>
</tr>
</tbody>
TS file for above code :
export class AppComponent {
showEditTable = false;
editRowId: any = '';
selectedRow;
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
dataSource = ELEMENT_DATA;
editTableRow(val) {
console.log('click event started val = ' + val);
this.editRowId = val;
console.log('click event ended with val = ' + val);
}
}
I expect the result as table where last 2 column can be edited inline and at the same time i can send modified data to backend
Naman, it's the same, you need use <ng-container>to avoid create extra tags, so your columns becomes like
<!-- Weight Column -->
<ng-container matColumnDef="weight">
<th mat-header-cell *matHeaderCellDef> Weight </th>
<td mat-cell *matCellDef="let element">
<ng-container *ngIf="element.position!==editRowId">
<span (click)="edit(element.position,'weigth')">{{element.weight}} </span>
</ng-container>
<ng-container *ngIf="element.position===editRowId">
<input matInput name="weigth" [(ngModel)]="element.weight">
</ng-container>
</td>
</ng-container>
Well, I call to function "edit" passign two arguments, the position and a string indicate the "name" of the input attributes. This allow us "focus" the input clicked. how?
We declare a ViewChildren of the MatInputs
#ViewChildren(MatInput,{read:ElementRef}) inputs:QueryList<ElementRef>;
See that we get not the MatInput else the "ElementRef". This allow us, in out function edit get the element with the attributes name equal the string that pass as argument, and focus it. See that we need "enclosed" all in a setTimeout to allow Angular to show the input
edit(row,element)
{
this.editRowId=row;
setTimeout(()=>{
this.inputs.find(x=>x.nativeElement.getAttribute('name')==element)
.nativeElement.focus()
})
}
You can see the full example in stackblitz
Well, in the example the data is hardcoded. Let's go to imagine that the data (and the structure) comes from a service data. The data is easy imagine because it's the same. The "structure" we can imagine as an array of object with three properties: name,head ad fixed. if fixed is true, we only show the data, else we can edit. So the only thing we need is create the columns in a *ngFor
First we are going to see how our schema can be defined. It's only an array
[
{name:'position',head:"No.",fixed:true},
{name:'name',head:"Name",fixed:true},
{name:'weight',head:"Weigth",fixed:false},
{name:'symbol',head:"Symbol",fixed:false},
]
Our table becomes like
<table #table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container *ngFor="let column of schema;let last=last">
<ng-container [matColumnDef]="column.name">
<th mat-header-cell *matHeaderCellDef> {{column.head}} </th>
<td mat-cell *matCellDef="let element">
<ng-container *ngIf="element[schema[0].name]!==editRowId || column.fixed">
<span
(click)="column.fixed?editRowId=-1:
edit(element[schema[0].name],column.name)">
{{element[column.name]}}
</span>
</ng-container>
<ng-container *ngIf="element[schema[0].name]===editRowId && !column.fixed">
<input matInput [id]="column.name"
[(ngModel)]="element[column.name]"
(blur)="last?editRowId=-1:null">
</ng-container>
</td>
</ng-container>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
See that we "replace" element.position by element[column[0].name] -I supouse the first element of the schema will be the "key" and how we using [(ngModel)]="elemen[column.name]". Yes, to refererd to element.position we can refered too as elemen["position"] and remember we are iterating over "schema"
Another thing is that we are going to use "id", not "name". this is because if we using name, really Angular put as attrib some like: ng-reflect-name, and this don't allow us focus the input.
Finally we are get the data in the ngOnInit. We are going to use forkJoin to get together the schema and the data. A forkJoin only call and array of observables (in this case this.dataService.getSchema() and this.dataServide.getData, and return in an array the response of all the observables. We use the way
([variable1,variable2]) to store in "variable1" the first result and in variable2 the second result
ngOnInit()
{
forkJoin([this.dataService.getSchema(),this.dataService.getData()])
.subscribe(([schema,data])=>{
this.dataSource=data;
this.displayedColumns=schema.map(x=>x.name)
this.schema=schema
})
}
The displayedColumns must be an array with the names of the columns, but we need to store in an array the "schema" too.
In the stackblitz I create a service and "simulate" the observable using the rxjs creation operator of, in a real application the data becomes from a httpClient.get(....)
I've followed the Angular docs here https://angular.io/api/common/NgIf to create an NgIf else conditional over my Material Table. It is reading remote JSON file as API.
The API is twitter data and one of the fields I want to run condition on is 'replies'. If there are no replies, I want to replace the "0" with a "-".
I am getting the error
Can't have multiple template bindings on one element. Use only one attribute prefixed with * (" Replies
]*ngIf="hashtags.replies<1; else noReplies"> {{hashtags.replies}}
"):`
So it seems I cannot run NgIf and interpolate my data in the same element, I've tried all kinds of combinations in the HTML but I am real stuck.
HTML
<ng-container matColumnDef="replies">
<th mat-header-cell *matHeaderCellDef> Replies </th>
<td mat-cell *matCellDef="let hashtags" *ngIf="hashtags.replies<1; else noReplies"> {{hashtags.replies}} </td>
<ng-template #noReplies>-</ng-template>
</ng-container>
Try
<ng-container matColumnDef="replies">
<th mat-header-cell *matHeaderCellDef> Replies </th>
<ng-container *matCellDef="let hashtags">
<td mat-cell *ngIf="(hashtags.replies>0); else noReplies"> {{hashtags.replies}} </td>
</ng-container>
<ng-template #noReplies>-</ng-template>
</ng-container>
The reason for getting this error is because your can't put 2 structural directives on the same DOM
In your code, you were using *matCellDef and *ngIf on the same <td>.
you can do it this way...... xd
<ng-container matColumnDef="estadoRevision">
<mat-header-cell *matHeaderCellDef mat-sort-header>Revision</mat-header-cell>
<mat-cell *matCellDef="let element">
<td *ngIf="element.a === 0"> ejemplo </td>
<td *ngIf="element.a === 1"> ejemplo </td>
</mat-cell>
</ng-container>
Is there any reason you can't do the conditional directly in the interpolation?
<td mat-cell *matCellDef="let hashtags">{{hashtags.replies > 0 ? hashtag.replies : '-'}}</td>
I am trying to make reusable material table and I want to use TemplateRef with ngTemplateOutlet to generate columns. In this example I created cards components which is using my material-table component. In cards.component.html I have template of one of my table's column. Running the project will cause an error ERROR TypeError: Cannot read property 'template' of undefined (see console on stackblitz). Is it possible to pass columnt template to my MaterialTableComponent and use it to define column?
<table mat-table [dataSource]="data" class="mat-elevation-z4">
<ng-container
*ngFor="let column of displayedColumnObjects"
[matColumnDef]="column.id"
>
<!-- if where is cellTemplate in table config json, use cellTemplate -->
<ng-container
*ngIf="column.cellTemplate"
[ngTemplateOutlet]="column.cellTemplate"
>
</ng-container>
<ng-container *ngIf="!column.cellTemplate">
<th mat-header-cell *matHeaderCellDef> {{column.title}} </th>
<td mat-cell *matCellDef="let element"> {{element[column.id]}} </td>
</ng-container>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let row; columns: columnsToDisplay;"></tr>
</table>
UPDATE
I found solution using ngTemplateOutletContext.
<table mat-table [dataSource]="data" class="mat-elevation-z4">
<ng-container
*ngFor="let column of displayedColumnObjects"
[matColumnDef]="column.id"
>
<ng-container
*ngIf="column.cellTemplate"
>
<th mat-header-cell *matHeaderCellDef> {{column.title}} </th>
<td mat-cell *matCellDef="let element">
<ng-template
[ngTemplateOutletContext]="{
element: element[column.id]
}"
[ngTemplateOutlet]="column.cellTemplate">
</ng-template>
</td>
</ng-container>
<ng-container *ngIf="!column.cellTemplate">
<th mat-header-cell *matHeaderCellDef> {{column.title}} </th>
<td mat-cell *matCellDef="let element"> {{element[column.id]}} </td>
</ng-container>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let row; columns: columnsToDisplay;"></tr>
</table>
See my example
ADD THE FOLLOWING IN THE COMPONENT TO BE RE-USED
In the '.HTML' file:
<ng-container [ngTemplateOutlet] = "yourNameReference"
[ngTemplateOutletContext] = "{$ implicit: {name: 'Arthur', lastName: 'Lemos'}">
</ng-container>
[NgTemplateOutletContext] data will be sent to the parent component. Remembering that '$ implicit' can receive any data you want to send to the PAI component
In the '.ts' file OF THE REUSABLE COMPONENT add the following code WITHIN YOUR CLASS
#ContentChild ('yourNameReference') yourNameReference: TemplateRef <any>;
FATHER COMPONENT (RECEIVES THE RE-USED COMPONENT)
Add the following code to the '.html' file
<ng-template #yourNameReference let-myDataa>
<p> {{myDataa.name}} {{myDataa.lastName}} </p>
</ng-template>
That way you can send data from the child component to the parent component, so you can create dynamic columns for your table.
Just follow the steps above, however, applying the specific columns of the table ... EX:
<td> <ng-container [ngTemplateOutlet] = "yourNameReference"
[ngTemplateOutletContext] = "{$ implicit: {name: 'Arthur', lastName: 'Lemos'}">
</ng-container> </td>
Add to the child's .ts:
#ContentChild ('yourNameReference') yourNameReference: TemplateRef <any>;
In the parent component:
<my-table>
...
<ng-template #yourNameReference let-myDataa>
<p> {{myDataa.name}} {{myDataa.lastName}} </p>
</ng-template>
<! - this content will be rendered inside the table ... ->
...
</my-table>
YOU CAN CREATE A REFERENCE NAME FOR EACH COLUMN, AND REPEAT THE PROCESS
ANGLE VERSION: 9
DOCUMENTATION: https://angular.io/api/common/NgTemplateOutlet
The documentation does not show the use of ngTemplateOutlet in different components, but it already helps in something.