How can you make the *ngIf more compact? - html

Is it possible to somehow put the condition for changing the icon in one line?
Example #1
<ng-template [ngIf]="isMenuCollapsed" [ngIfThen]="open" [ngIfElse]="close">
</ng-template>
<ng-template #open>
<fa-icon [icon]='["fas", "bars"]'></fa-icon>
</ng-template>
<ng-template #close>
<fa-icon [icon]='["fas", "times"]'></fa-icon>
</ng-template>
Example #2
<fa-icon [icon]='["fas", "bars"]' *ngIf="isMenuCollapsed"></fa-icon>
<fa-icon [icon]='["fas", "times"]' *ngIf="!isMenuCollapsed"></fa-icon>

Yes, with method for example:
<fa-icon [icon]='getIcon()'></fa-icon>
In TS something like:
getIcon = () => isMenuCollapsed ? ["fas", "bars"] : ["fas", "times"];

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>

Display row only if certain conditions are met

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.

ngx datatable footer icons not displaying

Not able to display the ngx datatable default footer properly.
Its showing the footer like this
My code
<ngx-datatable
#table
[columnMode]="'force'"
[headerHeight]="50"
[rowHeight]="'auto'"
[footerHeight]="50"
[count]="true"
[limit]="4"
[rows]="data"
>
<ngx-datatable-column [width]=10>
<ng-template let-row="row" ngx-datatable-cell-template>
<span class="circle" [ngClass]="{'red': row.alertCat == 'HIGH','yellow': row.alertCat == 'MEDIUM', 'green': row.alertCat == 'LOW'}"></span>
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column name="ID" [width]=10>
<ng-template let-column="column" ngx-datatable-header-template>
<strong class="text-uppercase alertHeading">ID</strong>
</ng-template>
<ng-template let-row="row">
{{row.id}}
</ng-template>
</ngx-datatable-column>
</ngx-datatable>
use node_modules/#swimlane/ngx-datatable/release/assets/icons.css in your main .scss file:
"styles": [
// ...
"node_modules/#swimlane/ngx-datatable/release/assets/icons.css"
],
If I am not wrong, your footer classes are being overridden by other classes. Inspect them and you will know or provide your icons like from font-awesome.
For ex
.datatable-icon-left {
content: #fa-var-chevron-left;
}

mat-list in angular 5

I have a question about implement mat-list in angular 5.
I had this code, when I had the divider insede the mat-list-item but the divider line didn't show always
<mat-list >
<mat-list-item class="pathitem" *ngFor="let item of Lst" style="height: 76px;">
<div>
<h3>item.title</h3>
<p>item.desc</p>
<p>item.ad</p>
</div>
<mat-divider class="background-divider"></mat-divider>
</mat-list-item>
</mat-list>
then I change that for this:
<mat-list *ngFor="let item of LstTramosFiltro" >
<mat-list-item class="pathitem" style="height: 76px;">
<div>
<h3>item.title</h3>
<p>item.desc</p>
<p>item.ad</p>
</div>
</mat-list-item>
<mat-divider class="background-divider"></mat-divider>
</mat-list>
My question is which of the two is the correct solution if you use ngfor in mat-list or use in mat-list-item; and where the use of the mat-divider is correct
thanks for your help.
First, ngfor should be placed in the mat-list-item instead of mat-list, otherwise you will get multiple list and each have multiple mat-list-item, and if you have multiple sections you can use mat-divider to divide into different sections, the mat-divider should be placed between two mat-list-item not inside the mat-list-item. Check https://material.angular.io/components/list/overview#lists-with-multiple-sections for details.
the first one is current. The item you need to iterate over is the one that should have ngFor. If you want to include the divider, you may wrap both items into ng-template like this:
<mat-list>
<ng-template *ngFor="let item of LstTramosFiltro">
<mat-list-item class="pathitem" style="height: 76px;">
<div>
<h3>item.title</h3>
<p>item.desc</p>
<p>item.ad</p>
</div>
</mat-list-item>
<mat-divider class="background-divider"></mat-divider>
</ng-template>
</mat-list>
You should use the ngFor for the mat-list-item, not mat-list, assuming you only want to display a single list of items.
Doc references: https://material.angular.io/components/list/examples, https://material.angular.io/components/divider/overview
If you want the divider to show after every item except the last, it can be inserted as part of the mat-list-item (which I think you did), like so:
<mat-list>
<mat-list-item class="pathitem" *ngFor="let item of Lst; last as last" style="height: 76px;">
<h3>item.title</h3>
<p>item.desc</p>
<p>item.ad</p>
<mat-divider class="background-divider" *ngIf="!last"></mat-divider>
</mat-list-item>
</mat-list>

*ngIf else if in template

How would I have multiple cases in an *ngIf statement? I'm used to Vue or Angular 1 with having an if, else if, and else, but it seems like Angular 4 only has a true (if) and false (else) condition.
According to the documentation, I can only do:
<ng-container *ngIf="foo === 1; then first else second"></ng-container>
<ng-template #first>First</ng-template>
<ng-template #second>Second</ng-template>
<ng-template #third>Third</ng-template>
But I want to have multiple conditions (something like):
<ng-container *ngIf="foo === 1; then first; foo === 2; then second else third"></ng-container>
<ng-template #first>First</ng-template>
<ng-template #second>Second</ng-template>
<ng-template #third>Third</ng-template>
But I'm ending up having to use ngSwitch, which feels like a hack:
<ng-container [ngSwitch]="true">
<div *ngSwitchCase="foo === 1">First</div>
<div *ngSwitchCase="bar === 2">Second</div>
<div *ngSwitchDefault>Third</div>
</ng-container>
Alternately, it seems like a lot of the syntaxes I've got used to from Angular 1 and Vue aren't supported in Angular 4, so what would be the recommended way to structure my code with conditions like this?
Another alternative is to nest conditions
<ng-container *ngIf="foo === 1;else second"></ng-container>
<ng-template #second>
<ng-container *ngIf="foo === 2;else third"></ng-container>
</ng-template>
<ng-template #third></ng-template>
You can just use:
<ng-template [ngIf]="index == 1">First</ng-template>
<ng-template [ngIf]="index == 2">Second</ng-template>
<ng-template [ngIf]="index == 3">Third</ng-template>
unless the ng-container part is important to your design I suppose.
Here's a Plunker
This seems to be the cleanest way to do
if (foo === 1) {
} else if (bar === 99) {
} else if (foo === 2) {
} else {
}
in the template:
<ng-container *ngIf="foo === 1; else elseif1">foo === 1</ng-container>
<ng-template #elseif1>
<ng-container *ngIf="bar === 99; else elseif2">bar === 99</ng-container>
</ng-template>
<ng-template #elseif2>
<ng-container *ngIf="foo === 2; else else1">foo === 2</ng-container>
</ng-template>
<ng-template #else1>else</ng-template>
Notice that it works like a proper else if statement should when the conditions involve different variables (only 1 case is true at a time). Some of the other answers don't work right in such a case.
aside: gosh angular, that's some really ugly else if template code...
You can use multiple way based on sitaution:
If you Variable is limited to specific Number or String, best way is using ngSwitch or ngIf:
<!-- foo = 3 -->
<div [ngSwitch]="foo">
<div *ngSwitchCase="1">First Number</div>
<div *ngSwitchCase="2">Second Number</div>
<div *ngSwitchCase="3">Third Number</div>
<div *ngSwitchDefault>Other Number</div>
</div>
<!-- foo = 3 -->
<ng-template [ngIf]="foo === 1">First Number</ng-template>
<ng-template [ngIf]="foo === 2">Second Number</ng-template>
<ng-template [ngIf]="foo === 3">Third Number</ng-template>
<!-- foo = 'David' -->
<div [ngSwitch]="foo">
<div *ngSwitchCase="'Daniel'">Daniel String</div>
<div *ngSwitchCase="'David'">David String</div>
<div *ngSwitchCase="'Alex'">Alex String</div>
<div *ngSwitchDefault>Other String</div>
</div>
<!-- foo = 'David' -->
<ng-template [ngIf]="foo === 'Alex'">Alex String</ng-template>
<ng-template [ngIf]="foo === 'David'">David String</ng-template>
<ng-template [ngIf]="foo === 'Daniel'">Daniel String</ng-template>
Above not suitable for if elseif else codes and dynamic codes, you can use below code:
<!-- foo = 5 -->
<ng-container *ngIf="foo >= 1 && foo <= 3; then t13"></ng-container>
<ng-container *ngIf="foo >= 4 && foo <= 6; then t46"></ng-container>
<ng-container *ngIf="foo >= 7; then t7"></ng-container>
<!-- If Statement -->
<ng-template #t13>
Template for foo between 1 and 3
</ng-template>
<!-- If Else Statement -->
<ng-template #t46>
Template for foo between 4 and 6
</ng-template>
<!-- Else Statement -->
<ng-template #t7>
Template for foo greater than 7
</ng-template>
Note: You can choose any format, but notice every code has own problems
Or maybe just use conditional chains with ternary operator. if … else if … else if … else chain.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator#Conditional_chains
<ng-container [ngTemplateOutlet]="isFirst ? first : isSecond ? second : third"></ng-container>
<ng-template #first></ng-template>
<ng-template #second></ng-template>
<ng-template #third></ng-template>
I like this aproach better.
To avoid nesting and ngSwitch, there is also this possibility, which leverages the way logical operators work in Javascript:
<ng-container *ngIf="foo === 1; then first; else (foo === 2 && second) || (foo === 3 && third)"></ng-container>
<ng-template #first>First</ng-template>
<ng-template #second>Second</ng-template>
<ng-template #third>Third</ng-template>
you don't need to use *ngIf if you use ng-container
<ng-container [ngTemplateOutlet]="myTemplate === 'first' ? first : myTemplate ===
'second' ? second : third"></ng-container>
<ng-template #first>first</ng-template>
<ng-template #second>second</ng-template>
<ng-template #third>third</ng-template>
<ion-row *ngIf="cat === 1;else second"></ion-row>
<ng-template #second>
<ion-row *ngIf="cat === 2;else third"></ion-row>
</ng-template>
<ng-template #third>
</ng-template>
Angular is already using ng-template under the hood in many of the
structural directives that we use all the time: ngIf, ngFor and
ngSwitch.
> What is ng-template in Angular
https://www.angularjswiki.com/angular/what-is-ng-template-in-angular/
I came a cross this type of situation *ngIf elseIf else and I solved using ng-template, Hope the following snippet may depicts briefly,
I have a form control named "NIC" and need to show one error message at a time when the form control invalid.
form: FormGroup = new FormGroup({
NIC: new FormControl('', [Validators.required, Validators.minLength(10), Validators.maxLength(10), Validators.pattern("^[0-9]*$")])
});
Template
<mat-form-field appearance="standard">
<mat-label>NIC Number</mat-label>
<input matInput placeholder="Enter NIC no" formControlName="NIC">
<mat-error *ngIf="form.controls['NIC'].errors?.required; else minvalue">This field is mandatory.
</mat-error>
<ng-template #minvalue>
<mat-error *ngIf="form.controls['NIC'].errors?.minlength; else maxvalue">Minimum 10 charactors
needed.
</mat-error>
</ng-template>
<ng-template #maxvalue>
<mat-error *ngIf="form.controls['NIC'].errors?.maxLength; else numericonly">Maximum 10
charactors allowed.
</mat-error>
</ng-template>
<ng-template #numericonly>
<mat-error *ngIf="form.controls['NIC'].errors?.pattern">
Numeric characters only.
</mat-error>
</ng-template>
</mat-form-field>
If you have a straightforward case in which some variable can take several values (for example, foo is of 1 | 2 | 3 type) just use the plain ngSwitch:
<ng-container [ngSwitch]="foo">
<div *ngSwitchCase="1">First</div>
<div *ngSwitchCase="2">Second</div>
<div *ngSwitchCase="3">Third</div>
</ng-container>
However, if you need a more sophisticated if-else logic it may be better and clearer to describe it inside the component's code and then turn its result into one of the set of states:
getLandformType(): 'continent' | 'island' | 'peninsula' {
if(this.pieceOfLand.bigEnough){
return 'continent';
}
else if(this.pieceOfLand.surroundedByWater){
return 'island';
}
return 'peninsula';
}
which, again, can be handled through ngSwitch:
<ng-container [ngSwitch]="getLandformType()">
<div *ngSwitchCase="'continent'">Continent</div>
<div *ngSwitchCase="'island'">Island</div>
<div *ngSwitchCase="'peninsula'">Peninsula</div>
</ng-container>
This approach also ensures that only one option can win at once, in contrast to that with three different *ngIf (without elses) blocks.
You can also use this old trick for converting complex if/then/else blocks into a slightly cleaner switch statement:
<div [ngSwitch]="true">
<button (click)="foo=(++foo%3)+1">Switch!</button>
<div *ngSwitchCase="foo === 1">one</div>
<div *ngSwitchCase="foo === 2">two</div>
<div *ngSwitchCase="foo === 3">three</div>
</div>