Any changes in ngModel field (click, focus) force ngTemplateOutlet re render - angular6

Need some help .... I've had dynamical templates for edit row in table
<ng-container [ngTemplateOutlet]="rowTemplate"
[ngTemplateOutletContext]="{
$implicit: rowData,
originalData: makeClone(rowData)
}">
</ng-container>
makeClone ...json.parse(json.stringlify())
.....
<ng-template #rowTemplate let-rowData let-originalData>
<tr>
<td><input [(ngModel)]="originalData.title"></td>
<td>
<button styleClass="ui-button-link" icon="icon-save" (click)="onSave(originalData, rowData)"></button>
</td>
</tr>
</ng-template>
But when I focused on input and on any changes - my template is re rendering ...and i loose originaldata ...
Show me pls right way to do it

Related

ERROR Error: dataKey must be defined to use row expansion

I'm trying to figure out how to use Row Expansion in PrimeEng. I was just following the guide in their documentation and it shows that I should define my datakey. I already defined it below if I'm not mistaken. I'm new to this, please don't judge.
<p-table [value]="users" [paginator]="true" [rows]="10" [showCurrentPageReport]="true"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"
[rowsPerPageOptions]="[10, 25, 50]">
<ng-template pTemplate="header">
<tr>
<th style="width:2rem">blank</th>
<th style="width:1rem">ID</th>
<th style="width:8rem">Name</th>
<th style="width:8rem">Username</th>
<th style="width:8rem">Email</th>
<th style="width:8rem">Street</th>
<th style="width:8rem">Suite</th>
<th style="width:8rem">City</th>
<th style="width:8rem">Zip code</th>
<th style="width:8rem">LAT</th>
<th style="width:8rem">LNG</th>
<th style="width:8rem">Phone</th>
<th style="width:8rem">Website</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-user let-expanded="expanded">
<tr>
<td>
<!-- <button type="button" pButton pRipple (click)="viewPostUser(user.id)" class="p-button-text p-button-rounded p-button-plain" ></button> -->
<button type="button" pButton pRipple [pRowToggler]="posts" (click)="viewPostUser(user.id)" class="p-button-text p-button-rounded p-button-plain" [icon]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></button>
</td>
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.username}}</td>
<td>{{user.email}}</td>
<td>{{user.address.street}}</td>
<td>{{user.address.suite}}</td>
<td>{{user.address.city}}</td>
<td>{{user.address.zipcode}}</td>
<td>{{user.address.geo.lat}}</td>
<td>{{user.address.geo.lng}}</td>
<td>{{user.phone}}</td>
<td>{{user.website}}</td>
</tr>
</ng-template>
Here is my row expansion ng-template.
<ng-template pTemplate="rowexpansion" let-posts>
<tr>
<td colspan="7">
<div class="p-p-3">
<p-table [value]="posts.userId" [dataKey]="posts.userId">
<ng-template pTemplate="header">
<tr>
<th style="width:4rem">userID</th>
<th style="width:4rem">ID</th>
<th style="width:4rem">Title</th>
<th style="width:4rem">Body</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-posts>
<tr>
<td>{{posts.userId}}</td>
<td>{{posts.id}}</td>
<td>{{posts.title}}</td>
<td>{{posts.body}}</td>
<td><p-button type="button" icon="pi pi-search"></p-button></td>
</tr>
</ng-template>
</p-table>
</div>
</td>
</tr>
</ng-template>
I've tried searching the error that I have, but it points me to updating the version.
I think here is where you get it wrong:
[value]="posts.userId" [dataKey]="posts.userId"
[value] is the collection that you want to iterate through, which should be posts in this case
[dataKey] is the property of one item in that collection which you could just define by name: userId
So the final code is:
[value]="posts" [dataKey]="userId"
First, to fix the error you're seeing, add the attribute dataKey="id" to the p-table element.
Next, using let-posts is probably not what you wanted. You didn't write how your data structure is constructed but I'll assume each user has a property called posts. You need to change your template like this:
<ng-template pTemplate="rowexpansion" let-user>
<tr>
<td colspan="7">
<div class="p-p-3">
<p-table [value]="user.posts" dataKey="id">
<ng-template pTemplate="header">
<tr>
<th style="width:4rem">userID</th>
<th style="width:4rem">ID</th>
<th style="width:4rem">Title</th>
<th style="width:4rem">Body</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-post>
<tr>
<td>{{post.userId}}</td>
<td>{{post.id}}</td>
<td>{{post.title}}</td>
<td>{{post.body}}</td>
<td><p-button type="button" icon="pi pi-search"></p-button></td>
</tr>
</ng-template>
</p-table>
</div>
</td>
</tr>
</ng-template>
Explanation:
Use let-user in the rowexpansion template. Now the user variable will contain the user data for the current expandable row.
In the inner p-table, provide the [value] input with the data for the sub table, i.e., the posts for the current user.
In the inner p-table, provide the dataKey input with the name of the field which is the unique key of the table. This might be even not necessary in your case.
In the inner p-table, in the body template, use let-post instead of let-posts since each iteration, i.e., each row of the inner table showing posts for the user, will store the current row, which is a single post.
In each <td> element in the inner table's body template, use post.<field-name>. post will contain the data for the current row so all you need to do is access the field you need inside the object.
You can add dataKey in first line, like this
<p-table [value]="users" dataKey="name">
Maybe it will solve your problem.

Toggle table row based on if condition not working

Need to toggle one table row based on if condition not working.
If status id none I need to open a form in popup but if status is done popup shouldn't open.
<ng-container *ngFor="let person of personList |
searchFilter:searchValue;index as i">
<tr *ngIf="person.status == 'none'"
data-toggle="modal" data-target="#personModal"
(click)="function(person.id)">
<tr *ngIf="person.status == 'done'" >
<td>Place</td>
<td>Job</td>
</tr>
</tr>
</ng-container>
When I tried this solution the row is not displaying in the table list
Probably you should do something like this:
<ng-container *ngFor="let person of personList | searchFilter:searchValue;index as i">
<tr *ngIf="person.status == 'none'" data-toggle="modal" data-target="#personModal"
(click)="someFunction(person.id)">
<td>Place</td>
<td>Job</td>
</tr>
<tr *ngIf="person.status == 'done'" >
<td>Place</td>
<td>Job</td>
</tr>
</ng-container>
But it's important to see your TypeScript code. You should make a Stackblitz example.

How can I assign id to rows dynamically in table? [duplicate]

This question already has an answer here:
how to set index variable in primeng p-table like in ngFor
(1 answer)
Closed 1 year ago.
I am using p-table -> https://primefaces.org/primeng/showcase/#/table/dynamic
I want to assign unique id to each row dynamically.
<ng-template pTemplate="body" let-rowData let-columns="columns" let i="index">
<tr id=i>
<td *ngFor="let col of columns">
{{rowData[col.field]}}
</td>
</tr>
</ng-template>
Above code doesnt assign id to the row.
You can try something like this
<ng-template pTemplate="body" let-rowIndex="rowIndex">
<tr>
<td>{{rowIndex}}</td>
</tr>
</ng-template>
if you want to access it in your component you can use such thing
<ng-template pTemplate="body" let-rowData let-columns="columns" let-rowIndex="rowIndex">
<tr [pSelectableRow]="rowData" [pSelectableRowIndex]="rowIndex">
<td *ngFor="let col of columns">
{{rowData[col.field]}}
</td>
</tr>
</ng-template>
btw in order to see more examples, you can navigate to the primeng website:
https://primefaces.org/primeng/showcase/#/table

I need to get a checkbox already checked with angular material

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>

Display more information after clicking in row of table in angular

I have a table which contains list of informations from the database my problem how I can display the information of each line ,below this line,in other words i want more information about this line.
I have already managed to display the information but below the table .
<tbody>
<ng-container>
<tr *ngFor="let affectation of affectations">
<td>{{affectation[1]}}</td>
<td>{{affectation[2] }}</td>
<td>{{affectation[3]}}</td>
<td><button type="button" class="btaction"
(click)="getAffectationForEmploye(affectation[0])">Actionner</button></td>
--after clicking show more information about the line of table 1
</tr>
--show informations about the line of table 1
<tr [hidden]="!visionnerTableau" class="trDisplay" *ngFor="let affecter of affecters">
<td>{{affecter.fiche.nom}}</td>
<td>{{affecter.fiche.prenom}}</td>
<td>{{affecter.fiche.produit.nom_produit}}</td>
</tr>
</ng-container>
</tbody>
you should place the first for loop on the ng-container and if you just want to show information of 1 line at a time, you can use the index for this and a selectedItemIndex in your component and probably an ngIf instead of hidden to only invoke getAffectationForEmploye for the selected item. So something like this:
<tbody>
<ng-container *ngFor="let affectation of affectations; let i = index;">
<tr>
<td>{{affectation[1]}}</td>
<td>{{affectation[2] }}</td>
<td>{{affectation[3]}}</td>
<td><button type="button" class="btaction"
(click)="selectedItemIndex = index;">Actionner</button></td>
--after clicking show more information about the line of table 1
</tr>
--show informations about the line of table 1
<ng-container *ngIf="selectedItemIndex === index">
<tr class="trDisplay" *ngFor="let affecter of getAffectationForEmploye(affectation[0])">
<td>{{affecter.fiche.nom}}</td>
<td>{{affecter.fiche.prenom}}</td>
<td>{{affecter.fiche.produit.nom_produit}}</td>
</tr>
</ng-container>
</ng-container>
</tbody>