Disable mat icon into mat-tree-node - html

I need the answer to this question: is it possible to disable a mat-icon within a mat-tree-node?
So let me show you my code. Seeing the present mat-tree-node:
<mat-tree [dataSource]="ListView" [treeControl]="treeControl">
<mat-tree-node
*matTreeNodeDef="let node"
matTreeNodePadding
matTreeNodePaddingIndent="20"
class="mat-tree-node node-level-last hover"
>
<button class="cursor-default" mat-icon-button disableRipple="true"></button>
<div class="zone-action">
<div > {{ node.item.name }} </div>
<div class="icon-hover" *ngIf="!node.item.CanVisualize">
<div *ngIf="isEnabled">
<mat-icon
svgIcon="pencil"
color="primary"
(click)="actionReport(node.item, 'update'); $event.stopPropagation()"
></mat-icon>
</div>
</div>
</div>
</mat-tree-node>
I would like to have access to a list openened by the selection of a mat-tree-node, but I can't for the moment. So you have the property-binding " {{ node.item.name }} " that displays an information relative to the object selected which you need to know so as to proceed into the navigation of the component and it is needed to disable or hide the mat-icon inside <div *ngIf="isEnabled">.
But adding a structural directive like an ng-if in the HTML parent Node erase the node.item.name, printing an empty field, which behavior is clearly not the one searched.

Suggestion
<button mat-icon-button ngIf="isEnabled" (click)="actionReport(node.item, 'update'); $event.stopPropagation()">
<mat-icon>favorite</mat-icon>
</button>
<button mat-icon-button ngIf="!isEnabled" disabled>
<mat-icon>favorite</mat-icon>
</button>
https://material.angular.io/components/button/examples

Firstly, you should use a <button mat-icon-button> instead of the <mat-icon> directive:
<button mat-icon-button (click)="onButtonClick()">
<mat-icon>pencil</mat-icon>
</button>
vs
<mat-icon (click)="onButtonClick()">pencil</mat-icon>
Secondly, you can use the disabled input that the MatButton class (essentially a directive for button[mat-*-button]) exposes:
<button mat-icon-button [disabled]="isEnabled">
<mat-icon svgIcon="pencil"></mat-icon>
</button>
Note that the <mat-icon> directive does not support the disabled input.

Related

How to use ngIf inside a button?

I have a button
<button class="mx-2" mat-button type="button" (click)="close()"
name="buttonClose">
<mat-icon>cancel</mat-icon>
{{t('commonActions.cancel')}}
</button>
where i have to show the whole button when on PC but only show the button without commonActions.cancel when on mobile.
I use isMobile() function for that but i dont know where to place the ngIf, so that only the text gets added/removed, not the button or icon
You need to put the text in a text tag like (span, p ... ) and add the ngIf inside it , here's an example :
<button class="mx-2" mat-button type="button" (click)="close()"
name="buttonClose">
<mat-icon>cancel</mat-icon>
<span *ngIf="!isMobile()" >{{t('commonActions.cancel')}}</span>
</button>
your best option is to use <ng-container> in this case:
<ng-container *ngIf="!isMobile()">{{t('commonActions.cancel')}}</ng-container>

how to style a selected mat-button in an angular application

I have an Angular application where the user has multiple choices with buttons and when a button is pressed another component will display. The component depends on the user's choice.
One thing I'm trying to implement is the styling of the buttons to make it clear which choice has been selected.
<div fxLayout="row" fxLayoutAlign="space-between center" fxFill>
<div *ngFor="let button of buttons">
<button
mat-stroked-button
*ngIf="button.type === 'button'"
(click)="buttonPressed()"
ngxScrollTo
>
{{ button.text }}
</button>
</div>
<div fxLayout="row" fxLayoutAlign="space-between center">
<div *ngIf="item.hasSomeProperty | isTypeButton">
<button mat-mini-fab (click)="buttonPressed()">
<mat-icon>close</mat-icon>
</button>
</div>
</div>
I have also attached a picture of what im trying to achieve here:
Any help would be much appreciated.
Simply use [ngClass] or [ngStyle]:
<div *ngFor="let button of buttons">
<button
mat-stroked-button
*ngIf="button.type === 'button'"
[ngClass]="{'disabledButton': !button.selected}"
(click)="buttonPressed(button)"
ngxScrollTo
>
{{ button.text }}
</button>
</div>
Assuming that your button model contains the "selected" property (or you have some other model storing information which button was actually clicked):
buttonPressed(button: Button) {
// Mark only button as selected
this.buttons.forEach(b => b.selected = b === button);
}
And of course add some class in the css:
.disabledButton {
opacity: 0.75;
}
Note - writing this from top of my head (since no stackblitz was provided) so some adjustments might be needed.

Angular material - Menu click event for menu A is also being used for menu B

I'm building a coffee shop app with Angular and Angular Material. I have 3 menus, one for cup size and another two for setting the amount of cream & sugar separately.
The first menu works fine but for some reason, the "click" event of setting the creams number is also occurring for the sugar menu. By this, I mean that if I click one of the sugar options, it will apply it to the creams and change its value but not the sugar one. E.g. I click "3" when I open the sugar menu but instead I will see "Creams: 3" and "Sugars: 0". I'm not sure why it's happening here but the first menu isn't affected at all from there being another menu below it.
Here is a stackblitz link that tried to replicate the issue but for some reason menus from angular material don't work: https://stackblitz.com/edit/angular-ivy-5pgvtm
<div>
<button mat-button [matMenuTriggerFor]="menu">Size: {{drink.currentSize}}</button>
<mat-menu #menu="matMenu">
<button mat-menu-item *ngFor="let size of drink.productOptions"
(click)="drinks[i].currentSize = size[0]">{{size[0]}}</button>
</mat-menu>
<button mat-button (click)="addMenuItemToCart(drink)">Add to cart</button>
<div *ngIf="drink.type ==='HC' || 'IC'">
<div>
<button mat-button [matMenuTriggerFor]="menu">Creams: {{drink.creams}}</button>
<mat-menu #menu="matMenu">
<button mat-menu-item *ngFor="let cream of [1,2,3,4]" (click)="drink.creams=cream">{{cream}}</button>
</mat-menu>
</div>
<div>
<button mat-button [matMenuTriggerFor]="menu">Sugars: {{drink.sugars}}</button>
<mat-menu #menu="matMenu">
<button mat-menu-item *ngFor="let sugar of [1,2,3,4]" (click)="drink.sugars=sugar">{{sugar}}</button>
</mat-menu>
</div>
</div>
</div>
<button mat-button [matMenuTriggerFor]="menuCustomId">Creams: {{drink.creams}}</button>
<mat-menu #menuCustomId="matMenu">
...
<button mat-button [matMenuTriggerFor]="menuCustomId2">Creams: {{drink.creams}}</button>
<mat-menu #menuCustomId2="matMenu">
...
all your menus have the same id, give them unique id's. you also need to update the triggerFor binding to use the right ID. In your stackblitz example the only issue was the browserAnimations haven't been imported.

How do I get a button used on multiple card containers to only affect one container at a time?

I am currently working on a web application using angular and angular material. The page in question holds several profiles each with a button that when clicked removes the information currently showing and replaces it with the rest of the profile information. The issue is that when I click this button on one profile it does this information flip on all the profiles at once. I need help figuring out how to have the button only affect the profile it is associated with.
I am still relatively new to coding, so I've mainly been doing research on advice on how to approach this particular situation, but nothing I've found so far has worked.
<mat-card class="bpBuddyCont" *ngFor= "let profile of profileList">
<div>
<ul class="bpBuddies">
<li class="li2">
<div *ngIf="!showHiddenInfo">
<mat-card-title class="specifics">{{profile.dogName}}</mat-card-title>
<mat-card-subtitle class="subtitle">Owner ~ {{profile.ownerFirstName}}</mat-card-subtitle>
<mat-card-subtitle>Member Since {{profile.yearJoined}}</mat-card-subtitle>
</div>
<div class="column4" *ngIf="showHiddenInfo">
<span class="details4">Additional Notes: </span>
<span class="details3">{{profile.additionalNotes}}</span>
</div>
</div>
<button mat-button color="primary" class="btn" (click)="showHiddenInfo = !showHiddenInfo">{{showHiddenInfo ? 'Back' : 'More...'}}</button>
</li>
</ul>
</div>
</mat-card>
You can extend the profile object with
profile.showHiddenInfo and set it as false initially.
For this in your js(most probably the component file) after getting profileList,
profileList.forEach((profile, index) => {
angular.extend(profile, {showHiddenInfo: false});
//not sure about this angular.extend but you need to extend your object here
});
Now when the button is clicked replace showHiddenInfo, i.e.
profile.showHiddenInfo = !profile.showHiddenInfo;
And Replace
*ngIf="showHiddenInfo"
with
*ngIf="profile.showHiddenInfo"
You can do this using one boolean variable for each object, as profile.isExpanded and on click change it as like:
(click)="profile.isExpanded = !profile.isExpanded"
HTML Code:
<mat-card class="bpBuddyCont" *ngFor="let profile of profileList">
<div>
<ul class="bpBuddies">
<li class="li2">
<div *ngIf="!profile.isExpanded">
<mat-card-title class="specifics">{{profile.dogName}}</mat-card-title>
<mat-card-subtitle class="subtitle">Owner ~ {{profile.ownerFirstName}}</mat-card-subtitle>
<mat-card-subtitle>Member Since {{profile.yearJoined}}</mat-card-subtitle>
</div>
<div class="column4" *ngIf="profile.isExpanded">
<span class="details4">Additional Notes: </span>
<span class="details3">{{profile.additionalNotes}}</span>
</div>
<button mat-button color="primary" class="btn" (click)="profile.isExpanded = !profile.isExpanded">{{profile.isExpanded ? 'Back' : 'More...'}}</button>
</li>
</ul>
</div>
</mat-card>
No change in TS file.
WORKING STACKBLITZ

Line break in ngFor loop

I have an ngFor that creates several PrimeNG buttons. Right now, the buttons appear directly after each other on the same row - I would like each button to display on its on line vertically. How do you go about doing that? Here is my ngFor code:
<button pButton type="button"
*ngFor="let atrConfig of atrConfigs; let i = index"
(click)="selectConfiguration(atrConfig)" label = "">
Name: {{atrConfig.name}} <br />
</button>
You should use a ng-container tag which groups elements but doesn't get rendered in the DOM tree as a node.
<ng-container *ngFor="let atrConfig of atrConfigs; let i = index" >
<button pButton type="button"
(click)="selectConfiguration(atrConfig)" label = ""> Name: {{atrConfig.name}}
</button>
<br />
</ng-container>
In this example, it may be just as simple to use CSS, but ng-container can be very useful if you don't want a surrounding div e.g. populating a table
Just add a css class with display: block to your button.
Or add it inline like the next example:
<button pButton type="button" style="display: block;"
*ngFor="let atrConfig of atrConfigs; let i = index"
(click)="selectConfiguration(atrConfig)" label = "">
Name: {{atrConfig.name}} <br />
</button>
I don't have idea if the pButton directive adds styles to the button that can override the display value.