Display row only if certain conditions are met - html

I'm a intern, and I need some help.
I've a ngx-datatable, and I want to display row when condition are met. How can I do it? For example, if country covered is America, I display, if not, I didn't.
<ngx-datatable class="table-zenmoov" [columnMode]="'force'" [rows]="rows" [rowHeight]="'auto'"
[headerHeight]="'auto'" [footerHeight]="'auto'" [externalPaging]="true" [count]="paginationInfo.totalElements"
[loadingIndicator]="loadingIndicator"
[offset]="paginationInfo.currentPage" [limit]="paginationInfo.pageSize" (page)="setTablePage($event)"
(sort)="onSort($event)">
<ngx-datatable-column name="Name" [prop]="'first_name'" [sortable]="true">
<ng-template let-row="row" ngx-datatable-cell-template>
<div class="user-wrap">
<div class="zenmoov-vendor" [style.background]="row.company_id?'#f0ad4e':'#5bc0de'"></div>
<div class="img-circle img-wrapper vendor-avatar">
<img *ngIf="row.avatar_url" [src]="row?.avatar_url " alt="logo">
</div>
<ng-container *ngIf="auth.userRID=='admin'">
<a [routerLink]="['../../vendor/',row._id]">{{ row?.first_name }} {{ row?.last_name }}</a>
</ng-container>
<ng-container *ngIf="auth.userRID=='hr'">
<a [routerLink]="['../../../vendor/',row._id]">{{ row?.first_name }} {{ row?.last_name }}</a>
</ng-container>
<ng-container *ngIf="auth.userRID=='talent'">
<a [routerLink]="['/talent/vendor/',row._id]">{{ row?.first_name }} {{ row?.last_name }}</a>
</ng-container>
</div>
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column name="Company" [sortable]="false">
<ng-template let-row="row" ngx-datatable-cell-template>
{{ row?.company_name }}
</ng-template>
</ngx-datatable-column>
</ngx-datable class>

You can use *ngIf on html element and it will be displayed only if the conditions are met.

I have never used ngx-datatable however, from a quick look into the documentation and your code I think I got it. I suppose that this bit [rows]="rows" is where you feed your data to the datatable, what you need to do is filter out the objects you don't want to be in the datatable, something like this in your TypeScript file:
TypeScript File
// Array of strings that contains all countries in America
const americaCountries = [...];
// Iterate over each row and verify if the country of that row is in the array americaCountries
// If it is, that row is added to a new array named americaRows
this.americaRows = this.rows.filter(row => americaCountries.includes(row.country));
HTML File
[rows]="americaRows"
Bear in mind that this is pseudo code because I don't know your TypeScript code and the rows object structure.

Related

same confirmation dialog box but different message

Is there a way on how to use the same code for the confirmation message but the message is different? I just want to reuse the existing code and change only the message instead of creating another function. Is it possible?
<p-dialog [(visible)]="openDialogBox1" [style]="{ width: '50vw' }" modal="true" [closable]="false">
<ng-template pTemplate="header">
<h3>Confirm ABC?</h3>
</ng-template>
<p>Are you sure you want to tag as ABC?</p>
</p-dialog>
<p-dialog [(visible)]="openDialogBox2" [style]="{ width: '50vw' }" modal="true" [closable]="false">
<ng-template pTemplate="header">
<h3>Confirm include the company?</h3>
</ng-template>
<p>Are you sure you want to inlcude the company? This will include the sub unit.</p>
</p-dialog>
Make the Dialogbox as Reusable component.
<p-dialog [(visible)]="openDialogBox" [style]="{ width: '50vw' }"
modal="true" [closable]="false">
<ng-template pTemplate="header">
<h3>{{ messageHeader }}</h3>
</ng-template>
<p>{{ messageBody }}</p>
</p-dialog>
Add the following variables in your ts file of the corresponding component.
#Input() messageHeader!: string;
#Input() messageBody!: string;
Use the component as below where ever you need.
<app-component-name [messageHeader] = "content" [messageBody] = "content"></app-component-name>

why there is extra comment tag in the final DOM generate by angualr

bindings={
“ng-reflect-ng-if”: “false”
}
<ng-template class=“no-result-product” [ngIf]=“products” [ngIfElse]=“noproducts”>
<div class=“list-product” fxLayout=“row wrap” fxLayoutAlign=“center stretch” *ngIf=“products”>
<app-template-product *ngFor=“let product of products”
class=“list-product__item”
[product]=“product”>
</app-template-product>
</div>
</ng-template>
<ng-template #noproducts>
<div> <img src=“./assets/img/shop/not-found-product.svg” alt=“”>
<div >{{ ‘not.found.product.message’ | translate }}</div>
</div>
</ng-template>
{{ ‘not.found.product.message’ | translate }}
the content is not displayed !!
here you are using ngIf directive, and passing your 2nd template inside of ngIfElse property
<ng-template class=“no-result-product” [ngIf]=“products” [ngIfElse]=“noproducts”>
that means that your "else template" will appear if products value is falsy.

highlight word by start and end matches using angular 7

I have a collection of array which is having datas like
[0]: username {kavya} secret {password}
[1]: lorem ipsem text data value
[2]: lorem {{lrm}} datas {{pp}}
I am using foreach to show this data in frontend with
<div *ngFor="let data of output;let i=index">
<div *ngIf="data.includes('{') || data.includes('{{');else isNotEdited;" >
<div class="variable-textarea" contenteditable="false" >
<span>
{{data | slice:' ' }}
</span>
</div>
</div>
<ng-template #isNotEdited>
<ngx-md>{{data}}</ngx-md>
</ng-template>
</div>
Here I achieved like 0,2 row of div will be editable and in case of 1st array is non-editable.
But I want to do like specific matches which word starts with { or {{ and that particular word needs to be highlight and editable.
Is there any option to do in this way
Thanks in advance.
You could split the data into words:
<div *ngFor="let data of arr">
<span *ngFor="let word of data.split(' ')">
<span *ngIf="word.indexOf('{') > -1;else isNotEdited;">
<span class="variable-textarea-2" contenteditable="true">
{{word | slice:' ' }}
</span>
</span>
<ng-template #isNotEdited>
<span class="variable-text-2" contenteditable="false">
{{word}}
</span>
</ng-template>
</span>
</div>
Check this Stackblitz example I made based on your code: https://stackblitz.com/edit/angular-pkg6i9
this is a performance nightmare, you don't want to be running this many functions in template, and your format isn't helping you. map your data ahead of time into a friendlier view model:
this.mappedOutput = this.output.map(data => {
const editable = data.includes('{'); // checking for doubles is redundant
return {
editable,
data: !editable
? data
: data.split(' ')
.map(word => ({
word,
editable: word.trim().startsWith('{') && word.trim().endsWith('}')
}))
};
})
run this whenever your output changes, then use it in template:
<div *ngFor="let data of mappedOutput;let i=index">
<div *ngIf="data.editable;else isNotEdited;" >
<div class="variable-text">
<ng-container *ngFor="let word of data.data">
<div *ngIf="word.editable; else wordTmp" class="variable-textarea inline" contenteditable="true" >
<span>{{word.word}}</span>
</div>
<ng-template #wordTmp>
{{word.word}}
</ng-template>
</ng-container>
</div>
</div>
<ng-template #isNotEdited>
<ngx-md>{{data.data}}</ngx-md>
</ng-template>
</div>
and adjust the styles by adding this to your css:
.variable-textarea.inline {
display: inline-block;
width: fit-content;
margin: 0;
}
here's an edited blitz: https://stackblitz.com/edit/angular-arayve?file=src/app/app.component.html

Reference ngFor value in component

I have a nested ngFor statement. I need to retrieve the value of my first ngFor on button click.
I have tried the following:
use template reference variable
use attribute binding
use Input decorator
This is my code:
<mat-expansion-panel *ngFor="let item of Datasource;">
<mat-expansion-panel-header style="display:flex" class="mat-row">
{{item.Header}}
</mat-expansion-panel-header>
<mat-selection-list [(ngModel)]="selectedOptions">
<mat-list-option *ngFor="let line of item.match; let i= index;" [value]="line">
<div class="container-name">
<div class="col-6">{{i}} - {line.user.Name }} vs {{ line.user.Address }}</div>
</mat-list-option>
</mat-selection-list>
<div style="text-align:center; padding: 20px">
<button mat-raised-button color="primary" (click)="submit()" type="submit">Add</button>
</div>
</mat-expansion-panel>
Can this be achieved?
Well, you need to clone that object properties first. As that object is linked to the template, when you manipulate it, it is manipulated on template too. You can use var obj = Object.assign({}, actual obj) and then do the manipulation on obj instead of actual one. Then it will not get affected in template. Hope it helps.

Indirect Recursive Ng-Template in Angular 6

<ng-template #list let-Items>
<ul>
<li *ngFor="let i of Items">
<ng-container [ngTemplateOutlet]="container" [ngTemplateOutletContext]="{$implicit: i}"></ng-container>
</li>
</ul>
</ng-template>
<ng-template #container let-list>
// some code
<ng-container [ngTemplateOutlet]="list" [ngTemplateOutletContext]="
{$implicit: list.columns}"></ng-container>
</ng-template>
I have a template "container" that includes another template "item".. the container "item" includes "container" again
This is not working, I'm getting this error:
ERROR TypeError: templateRef.createEmbeddedView is not a function
Any ideas? Thanks.
This issue is quite old so you may already have found the answer but in case someone else encounter this.
The problem you had is a collision in the naming of the variable list (let-list) in your container template that overrides the list template.
If you rename the template to listTpl for example (or the variable) it should work correctly:
<ng-template #listTpl let-Items>
<ul>
<li *ngFor="let i of Items">
<ng-container [ngTemplateOutlet]="container" [ngTemplateOutletContext]="{$implicit: i}"></ng-container>
</li>
</ul>
</ng-template>
<ng-template #container let-list>
// some code
<ng-container [ngTemplateOutlet]="listTpl" [ngTemplateOutletContext]="
{$implicit: list.columns}"></ng-container>
</ng-template>
For recursion inside template, we need to understand how ng-template works along with templateOutlet in angular. If we master it the we could make the recursion easily For the reference follow following code.
<ul>
<ng-container *ngTemplateOutlet="recursiveListTmpl; context:{ $implicit: serviceNavLinks }"></ng-container>
</ul>
<ng-template #recursiveListTmpl let-list>
<li *ngFor="let item of list">
<a class="list-group-item no-border">
{{item.linkTranslationKey | translate }}
</a>
<ul *ngIf="item.childNavLinks && item.childNavLinks.length > 0">
<ng-container *ngTemplateOutlet="recursiveListTmpl; context:{ $implicit: item.childNavLinks }"></ng-container>
</ul>
</li>
This is tested in Angular 8. Did not checked for earlier versions of angular.