Is it possible to embed html in a ternary in angular expression? - javascript

I need different buttons with icon and text depending on the user.id but the html seems not to be interpreted in a ternary in an angular expression
I can have the result I want with a ngIf and two separated buttons but it would be better to do it in one line of code.
{{
user.id ?
'<i class="far fa-save"></i>Save' :
'<i class="far fa-plus-square"></i>Add'
}}
the expected result is having one icon and the corresponding text, for instance: ICON-ADD Add.
Instead of that, I have the entire expression: "user.id ? 'ICON-SAVE Save' : 'ICON-ADD Add'"

You can use ternary for inner text and ngClass to toggle classes as following:
<i class="far" [ngClass]="{'fa-save' : user.id, 'fa-plus-quare': !user.id}">
{{user.id ? 'Save' : 'Add'}}
</i>
Hope this helps.

Using *ngIf:
<ng-container *ngIf="user.id"> <i class="far fa-save"></i>Save </ng-container>
<ng-container *ngIf="!user.id"> <i class="far faplus-square"></i>Add </ng-container>
Using Ternary Operator
<ng-container>
<i [ngClass]="user.id ? 'far fa-save' : 'far faplus-square'"></i>
{{user.id ? 'Save' : 'Add'}}
</ng-container>

You can use ngif with else clause, here's the documentation:
https://angular.io/api/common/NgIf
In your case it'd look like that:
<i class="far fa-save" *ngIf='user.id; else showAdd'>Save</i>
<ng-template #showAdd>
<i class="far fa-plus-square">Add</i>
</ng-template>

Related

Applying a class to a array item which is not in the original array using angular

I have an array which displays data as mat-select dropdown. The user can select any tags he wants. Also we have some free form text field inside the dropdown of tags from which the user can create his own custom text apart from tags array. See below:
display.component.html
<mat-form-field class="full-width">
<mat-label class="full-width">Select Tag</mat-label>
<mat-select formControlName="tagsControl" [(ngModel)]="project.tags" multiple>
<mat-select-trigger>
<mat-chip-list>
<mat-chip *ngFor="let tagging of firstFormGroup.value.tagsControl" [removable]="true"
(removed)="onTaggingRemoved(tagging)">
{{ tagging }}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
</mat-select-trigger>
<mat-option *ngFor="let tagging of tagsList"
[value]="tagging">{{tagging}}</mat-option>
<mat-form-field style="margin-left: 17px; margin-top: 8px;">
<input matInput placeholder="Add New Tag" #input>
</mat-form-field>
<button mat-stroked-button color="primary" style="margin-left: 4px;" class="common-button"
(click)="addNewTags(input.value)">
Add</button>
</mat-select>
</mat-form-field>
display.component.ts
onTaggingRemoved(tagging: string){
const taggings = this.firstFormGroup.value.tagsControl as string[];
this.removeFirst(taggings, tagging);
this.firstFormGroup.controls['tagsControl'].patchValue(taggings);
}
removeFirst<T>(array: T[], toRemove: T): void {
const index = array.indexOf(toRemove);
if (index !== -1) {
array.splice(index, 1);
}
}
addNewTags(value: string) {
this.tagsList.push(value);
}
table.component.ts
tags: string[] = ["Prod", "Stg", "Dev", "QA"];
table.component.html
<ng-container matColumnDef="tags">
<mat-header-cell *matHeaderCellDef>
Tags </mat-header-cell>
<mat-cell *matCellDef="let element; let i = index;">
<span *ngIf="element.tags && element.tags.length < 35" matTooltipPosition="above"
matTooltip="{{element.tags}}">
<span *ngIf="element.tags == 'Prod'">
<span class="badge badge-pill bg-info font-color-tags">{{ element.tags.join(', ') }}</span>
</span>
<span *ngIf="element.tags == 'Stg'">
<span class="badge badge-pill bg-primary font-color-tags">{{ element.tags.join(', ')}}</span>
</span>
<span *ngIf="element.tags == 'Dev'">
<span class="badge badge-pill bg-secondary font-color-tags">{{ element.tags.join(', ')}}</span>
</span>
<span *ngIf="element.tags == 'QA'">
<span class="badge badge-pill bg-success font-color-tags">{{ element.tags.join(', ')}}</span>
</span>
</span>
<span *ngIf="element.tags.length == 0">
-
</span>
</mat-cell>
</ng-container>
My question is i am adding the badges the color codes to different array items based in its value. I mean if the tags array item value is "QA", i am adding different color, similarly for "Prod" different color. But i need to add some custom badge color to the custom tag which user created on his own other than tags array. I am planning to add a unique badge to all custom color badge then how to achieve this?
Please help me.
Not sur I got your question but if I did, you want to apply to any new tag in the four you have the correct badge.
In this way, your html code have to be dynamic with [ngClass] like :
<span [ngClass]="method_to_return_badge(element.tags)">{{ element.tags.join(', ')}}</span>
You then have to define the method_to_return_badge in your ts and with a switch on the four possibilities return the right badge.
This will let you write less code in your html and make it more readable.
Hope it helps you

Angular MatMenu not working in double ngFor loop

Using Angular 13, I have been trying to add a menu using Angular MatMenu (https://material.angular.io/components/menu/overview) which is conditionally shown. Basically a bar shows button (operations) and some may have suboperations. In this case I want to display the suboperations when clicking on the button.
Here is the basic code I have, which is the complete html since there is another menu in the beginning. Note that removing it does not change the behavior.
<div class="rounded-box" *ngIf="!!selectedCategory">
<div class="selector" *ngIf="rateOrDislocationEnabled; else simpleAggregation">
<button color="primary" mat-button mat-icon-button [matMenuTriggerFor]="categoryMenu" class="dropdownButton">
<div class="dropdownText">{{ selectedCategory | agReplace: "_":" " }}</div>
<mat-icon class="dropdownIcon">arrow_drop_down</mat-icon>
</button>
<mat-menu #categoryMenu="matMenu" [overlapTrigger]="true" data-testid="categories-menu">
<button mat-menu-item *ngFor="let category of availableCategories" (click)="setSelectedCategory(category)">
<span [ngClass]="{ selectedLabel: isSelected(category) }">{{ category | agReplace: "_":" " }}</span>
<div *ngIf="category === BlockCategory.RATE_MAKING" class="alpha">ALPHA</div>
</button>
</mat-menu>
</div>
<ng-container *ngFor="let operationCategory of getOperations(); let lastItem = last">
<ng-container *ngFor="let operation of operationCategory">
<button *ngIf="operation.subOperations.length === 0"
mat-icon-button
class="iconWrapper"
id="operation-icon-{{ operation.value }}"
(click)="addOperation(operation.value)"
[disabled]="operation.disabled$ | async">
<mat-icon [ngClass]="operation.icon" class="icon" [agToolTip]="operation.tooltip$ | async"></mat-icon>
</button>
<ng-container *ngIf="operation.subOperations.length !== 0">
<button
mat-button
mat-icon-button
class="iconWrapper"
id="operation-menu-icon-{{ operation.value }}"
[matMenuTriggerFor]="subMenu">
<mat-icon [ngClass]="operation.icon" class="icon" [agToolTip]="operation.tooltip$ | async"></mat-icon>
</button>
<mat-menu #subMenu="matMenu">
<button mat-menu-item>Settings</button>
<button mat-menu-item>Log off</button>
</mat-menu>
</ng-container>
</ng-container>
<div class="divider" *ngIf="!lastItem"></div>
</ng-container>
</div>
I have created a stackblitz reproducing the issue: https://angular-ivy-cvv2xk.stackblitz.io
The issue is that when I click on the button, nothing happens. When I move the button out of the ngFor loops though, it works properly. I have tried things such as removing the ngIf condition (so all buttons are doubled) and none show the menu when clicking on it.
So the "submenu" is never displayed.
I wonder if I need to make the mat-menu specific or give it some id to ensure there are no conflicts? Since I'm a bit new to Angular I maybe be missing something.
Thanks in advance
Your button which triggers submenu got multiple button tags.
<button
mat-button
mat-icon-button
Can you remove one and try again?
Edit:
You use <ng-container *ngFor="let operationCategory of getOperations();
to populate your array.
If you press your button, angular will trigger change detection and this will trigger again your getOperations().
This will lead to this behaviour and dosent open your submenu.
So you should try to replace getOperations() with async pipe (if this is the case) or use properties.

Text shown by uib-tooltip on a single line

Having the following code:
<i ng-if="!$ctrl.aggregated"
ng-class="!$ctrl.mainObj[item.name].hidden ? 'fa fa-check-square':'fa fa-square consumption-item__disabled'"
ng-style="{'color': item.color}"
ng-click="$ctrl.onItemClicked(item)"></i>
{{item.name}}
<i ng-if="!$ctrl.aggregated && $ctrl.multi"
class="fa fa-dot-circle-o fa-bullseye-position"
ng-click="$ctrl.onFocusClicked(item)"
uib-tooltip="this is my text"></i>
</div>
There is a tooltip at the end: uib-tooltip="this is my text" which is shown in two lines:
Is there a way to make it appear on one line the whole text?

Using a font awesome icon and text in a Datatables column header

There is probably an easy answer here but I am trying to put both text and a font awesome icon in the header of a datatable I am trying to update (should go after the the title - 1st line of code). So far I am just getting a blank or a square. Here's a block of code from the map. Anyone have any ideas? Does this have to be done in the CSS instead? Thanks
{title:'enabled' + '<i class="fa fa check green"></i>', class:'enabled small-screen small-screen-2-col', data:function(row, type, val, meta) {
var isEnabled = row.enabled || 0;
if (type=='display') {
return (isEnabled) ? '<i class="fa fa-check green"></i>' : '' ;
}
return isEnabled;
},
The first classname is wrong. It should be <i class="fa fa-check green"> instead of <i class="fa fa check green></i>. You forgot the dash between fa and check

How to disable NgbTooltip if tooltip template is empty, in Angular2?

I'm showing an array of data inside a tooltip, so I used a template. My code looks like:
<ng-template #ToolTipTemplate>
<small *ngFor="let month of data.months; let first = first; let last = last"> {{ month.appliedMonthYear | utc | date:'MM/y' }}{{ last ? '' : ', ' }} </small>
</ng-template>
<span [ngbTooltip]="ToolTipTemplate">Months: {{data.months.length}}</span>
If data.months is empty I do not want the tooltip to appear. Currently if it's empty it shows the tooltip arrow only.
I've tried adding an *ngIf on the <small> tag inside the template, but that didn't work. I've also tried adding *ngIf into <ng-template> to no avail.
Ok, I was finally able to figure it out. Here's what I had to do
<span [ngbTooltip]="(data.months?.length) ? ToolTipTemplate : ''">Months: {{data.months.length}}</span>
You can take the element reference like #t="ngbTooltip" and then manually fire the tooltip. In your case fire it if required or don't show the tooltip at all.
<div
[ngbTooltip]="(data.months?.length) ? ToolTipTemplate : ''"
triggers="manual"
#t="ngbTooltip"
(mouseenter)="(data.months?.length) && t.open()"
(mouseleave)="t.close()">
show Tooltip
</div>
You can disable it with
<span [ngbTooltip]="ToolTipTemplate" [disableTooltip]="true">Months: {{data.months.length}}</span>
See docs for more info: https://ng-bootstrap.github.io/#/components/tooltip/api
Simple way of doing is
<div *ngIf='data.months.length > 0'>
<ng-template #ToolTipTemplate>
<small *ngFor="let month of data.months; let first = first; let last = last"> {{ month.appliedMonthYear | utc | date:'MM/y' }}{{ last ? '' : ', ' }} </small>
</ng-template>
<span [ngbTooltip]="ToolTipTemplate">Show Info</span>
</div>
<div *ngIf='data.months.length === 0'>
<span>Show Info</span>
</div>
You can use disableTooltip input attribute.
https://ng-bootstrap.github.io/#/components/tooltip/api

Categories

Resources