I have a service that pull in a list of menu items and in *ngFor I load the items. The list of menu items includes also the status of the menu item.
service
buttonlist = [
{id: 1, menu: 'me', status: 'active',children: 2,3,4 },
{id: 2, menu: 'home', status: 'nonactive'},
{id: 3, menu: 'contact', status: 'nonactive'},
{id: 4, menu: 'location', status: 'nonactive'}
];
component
<ul>
<li *ngFor="let button of buttons " [ngClass]="'active' == buttons[subButton].status ? 'active' : 'hide'"
(click)="execCommand(button)"
>
{{button.id}}
<ul *ngFor="let subButton of button.children " >
<li
(click)="execCommand(button)"
[ngClass]="'active' == buttons[subButton].status ? 'active' : 'hide'"
>
{{buttons[subButton].status}} </li>
</ul>
</li>
</ul>
component functions
execCommand(button){
button.status = 'non-active';
}
If I log button status it does show that I have updated the object data but it is not rendered. How do make this button update status to show the active class?
My menu is basically id 1 is top level and the rest are children and onclick I would like to remove active on all the sibling children and only eave active the button i clicked, unless I click on top level than just have the top level active and all children.
I am not using routing, as I got one page application with several levels of menu items and if user clicks it loads a tab.
There is the thing that is called event propagation. When you click on the child item, execCommand(subButton)
is being called. But then the click event goes to the parent item and calls execCommand(button), so it makes all children active=false
. That's why I added (click)="execCommand(subButton, $event)"
and also $event.stopPropagation()
in the click handler.
import { Component, NgModule, OnInit } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@Component({
selector: 'my-app',
template: `
<ul>
<li *ngFor="let button of buttons " [ngClass]="button.active ? 'active' : 'hide'"
(click)="execCommand(button, $event)"
>
{{button.id}}(active: {{button.active|json}})
<ul *ngIf="button?.children" style="z-index: -1;" >
<li *ngFor="let subButton of button.children"
(click)="execCommand(subButton, $event)"
[ngClass]="subButton.active ? 'active' : 'hide'">
{{button.id}}(active: {{subButton.active|json}})
</li>
</ul>
</li>
</ul>
`
})
export class App implements OnInit {
buttons = [
{id: 1, menu: 'me', active: true, children: [
{id: 5, menu: 'sublvl1', active: false},
{id: 6, menu: 'sublvl2', active: false},
{id: 7, menu: 'sublvl3', active: false},
] },
{id: 2, menu: 'home', active: false},
{id: 3, menu: 'contact', active: false},
{id: 4, menu: 'location', active: false}
];
constructor() {}
ngOnInit() {}
execCommand(button: any, $event){
$event.stopPropagation();
this.buttons.forEach(b => {
b.active = false;
b.children && b.children.forEach(b => b.active = false);
});
button.active = true;
}
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}