How to implement Buttons depending on a list? - html

I want to generate and display as many buttons depending on the number of elements in my list. Can someone tell me how I can implement that?
Currently it is hardcoded like the below code. But often I only have a list with only button 1 and 2. And then I dont need the button 3 and button 4.
Thanks for your help!
list=[button1, button2, button3, button4]
<div class="tabs_item_categories">
<button class="tab_item_category" (click)="button1_active()">
Button1
</button>
<button class="tab_item_category" (click)="button2_active()">
Button2
</button>
<button class="tab_item_category"(click)="button3_active()">
Button3
</button>
<button class="tab_item_category" (click)="button4_active()">
Button4
</button>
</div>

You iterate with *ngFor structural directive in angular:
<div class="tabs_item_categories">
<button class="tab_item_category"
*ngFor="let buttonConfig of buttonConfigs"
(click)="buttonConfig.onClick()">
{{buttonConfig.label}}
</button>
</div>
and in your typescript:
buttonConfigs = [
{
label: 'Button 1',
onClick: this.doSomethingOnButton1Click
},
...
];
doSomethingOnButton1Click is lambda in the component.

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.

Disable mat icon into mat-tree-node

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.

Vue's v-for does not show correct text for modal window (only displays the first item's data)

I'm using Vue (just started learning it) and Bootstrap to make a blog and I want a modal window (that shows the post's name/etc) to pop up when the user clicks on the comment button. However, right now the modal window only gets the post information from the latest blog post. This means that even if you click the 1st post, you would get the id information and post title of the latest one... Any suggestions or solutions? Thanks in advance!
It seems that the main problem with my code is that it makes n numbers of modals in vue if you have n posts. I have tried slots but the modals started displaying the first post instead of the last one. I wonder if all my modals are being displayed at once but I only the last one... Should I use an index instead?
Is there any way to make only one modal that gets and display the information of the post clicked?
Here's my code of the post component
Vue.component('posts', {
props: ['post', 'loggedUser'],
template: `
<div class='blog-post py-2'>
<h3> {{post.title}} </h3>
<h6> Posted by {{post.postedBy}} on {{formatCompat(post.createdAt)}} </h6>
<span class='comments'>
<i class='far fa-comment-dots ml-3' data-toggle="modal" data-target="#commentModal"></i>
{{post.comments.length}}
</span>
</div>
`
My modal component: (mostly from the bootstrap docs)
Vue.component('modal', {
props: ['post'],
template: `
<div>
<div class="modal fade" id="commentModal" tabindex="-1" role="dialog" aria-labelledby="commentModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="commentModalLabel">Comment on {{post.postedBy}}'s post! ({{post.title}})</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
`
})
Here, I'd like the {{posted.title}} and other information to reflect the post where the comment button is clicked, but it's showing the latest post.
Parent element:
const postComponent = new Vue({
el: '#posts',
data: {
posts: null
},
methods: { // mostly code unrelated to modal stuff
}
My pug file:
#posts
if user
posts(name=username, v-for='post in posts' v-bind:post='post' v-bind:key="post.id" v-on:like-post='like' logged-user=loggedUser v-on:comment-post='comment')
modal(v-for='post in posts' v-bind:post='post' v-bind:key="post.id")
You need to add a custom data property that reflects the selected post for the template to read.
data: {
...
selected: '',
...
}
Then, you need a method that will assign the selected property to whichever post is clicked.
methods: {
changeTitle(postId) {
const currentPost = posts.filter((post) => {
return post.id == postId;
});
this.selected = currentPost.id;
}
}
So now that you have a data property to represent the current selected title, and a method to change that property with a click, you need to assign the directive for the method to the post. So, add this to the html tag you want to trigger the method:
#click = "changeTitle(postId);"
This will trigger the method along with the post id from the post that called the method. The current title can now be rendered anywhere in the template that has access to the data, like this:
{{selected}}

Toggle class between two buttons in Angular2

I am using angular 2 and I have two buttons I want toggle class between two buttons but. Below is my code
<button class="btn rounded" [ngClass]="{'btn-default': !clicked, 'btn-primary': clicked}" (click)="clicked = !clicked">
<i class="fa fa-long-arrow-up"></i>
</button>
<button class="btn rounded" [ngClass]="{'btn-default': !clicked, 'btn-primary': clicked}" (click)="clicked = !clicked">
<i class="fa fa-long-arrow-down"></i>
</button>
My problem is I want to toggle class but at time only one button can select and other condition is both buttons can be deselect. On click of one button other button should be deselect and once you click on selected button that button should be deselect and I want to do this only using buttons. Please help
You can use this pattern which will work for any number of buttons:
In your controller, set up an array of buttons and a selectedButton variable
buttons= [
{class: "fa fa-long-arrow-up", name: "button1"},
{class: "fa fa-long-arrow-down", name: "button2"},
]
selectedButton;
toggleSelect(button) {
if (button == this.selectedButton) {
this.selectedButton = undefined
} else {
this.selectedButton = button
}
}
Then in your template populate the selectedButton on click, and set your class based on whether it is selected
<button *ngFor="let button of buttons" class="btn rounded" [ngClass]="(selectedButton == button) ? 'btn-primary' : 'btn-default'" (click)="toggleSelect(button)">
<i [class]="button.class"></i>
</button>
This way you could have any number of buttons and only one will ever be "selected" at a time
working example: https://stackblitz.com/edit/angular-v9zlaz?file=src%2Fapp%2Fapp.component.html