I have a sidebar to display the job progress. Now I have three phases.
At the beginning the project has not started yet, so I want all sidebar items are greyed out. I want the current phase is based on the previous phases completion. On the right side there are three buttons. Here is the logic.
My ts code:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-sidenav',
templateUrl: './sidenav.component.html',
styleUrls: ['./sidenav.component.css']
})
export class SidenavComponent implements OnInit {
sidenavWidth = 10;
ngStyle: string;
active1: boolean;
active2: boolean;
active3: boolean;
constructor() {
}
ngOnInit() {
this.active1 = false;
this.active2 = false;
this.active3 = false;
}
submit1() {
this.active1 = true;
this.active2 = false;
this.active3 = false;
console.log('1');
}
submit2() {
this.active1 = true;
this.active2 = true;
this.active3 = false;
console.log('2');
}
submit3() {
this.active1 = true;
this.active2 = true;
this.active3 = true;
console.log('3');
}
}
My html:
<mat-sidenav-container fullscreen>
<mat-sidenav #sidenav mode="side" class="example-sidenav" [ngStyle]="{ 'width.em': sidenavWidth }" opened="true">
<div class="logomain">Project progress</div>
<mat-nav-list>
<mat-list-item routerLink="1" [routerLinkActive]="[active1]" >
<div fxFlex="10"></div>
<div *ngIf="sidenavWidth > 6" class="sidenav-item">
<h5 class="lead">Phase 1</h5>
</div>
</mat-list-item>
<mat-list-item routerLink="2" [routerLinkActive]="[active2]">
<div fxFlex="10"></div>
<div *ngIf="sidenavWidth > 6" class="sidenav-item">
<h5 class="lead">Phase 2</h5>
</div>
</mat-list-item>
<mat-list-item routerLink="3" [routerLinkActive]="[active3]">
<div fxFlex="10"></div>
<div *ngIf="sidenavWidth > 6" class="sidenav-item">
<h5 class="lead">Phase 3</h5>
</div>
</mat-list-item>
</mat-nav-list>
</mat-sidenav>
<!-- <div class="example-sidenav-content">
<router-outlet></router-outlet>
</div> -->
<br><br><br>
<section>
<br>
<div class="example-button-row">
<button mat-raised-button color="primary" (click) ="submit1()">Phase 1 completed</button>
</div>
</section>
<mat-divider></mat-divider>
<br>
<section>
<br>
<div class="example-button-row">
<button mat-raised-button color="primary" (click) = "submit2()">Phase 2 completed</button>
</div>
</section>
<br>
.<section>
<br>
<div class="example-button-row">
<button mat-raised-button color="primary" (click) = "submit3()">Phase 3 completed</button>
</div>
</section>
<br>
</mat-sidenav-container>
Here is the stackblize example.
My questions. When I click the buttons the side bar item are not greyed out by the condition. Also I am not sure how to apply the green color to the working phase.
Finally I have many items instead of 3 items in the example. I don't want manually to set boolean values in the click events.
Update:
The correct editable stackblitz link https://stackblitz.com/edit/angular-material-with-angular-sidenav-etrylt
It looks like you just need a simple structure to represent your Phases with a property to indicate if it is completed or not.
interface Phase {
id: number;
name: string;
isComplete: boolean;
}
Then, when you click a button, toggle the isComplete
property.
You can define an array of Phase
objects and use *ngFor
to repeat them in your template. This will prevent your template from growing when you add more phases.
sidebar.component.ts:
public phases = [
{ id: 1, name: "Phase 1", isComplete: false },
{ id: 2, name: "Phase 2", isComplete: false },
{ id: 3, name: "Phase 3", isComplete: false }
];
sidebar.component.html:
<mat-nav-list>
<mat-list-item *ngFor="let phase of phases">
<h5>{{ phase.name }}</h5>
</mat-list-item>
</mat-nav-list>
<section *ngFor="let phase of phases">
<button
(click)="togglePhaseComplete(phase)"
[disabled]="phase.isComplete"
>
{{ phase.name }} completed!
</button>
</div>
</section>
Then, you can use this isComplete
property in your template to disable buttons for phases that have already been completed:
[disabled]="phase.isComplete"
You can also make a little helper function to determine if a phase is Active or not in order to display your green background color:
public isActive(phase: Phase) {
// the first incomplete phase found is active
const activePhase = this.phases.find(p => !p.isComplete);
return phase.id === activePhase?.id;
}
Then just add [class.green]="isActive(phase)"
to your mat-list-item
(assuming you defined a class named "green" in your css).
Here's a working StackBlitz
Now, disabling the nav items for phases that haven't yet been active is a little more work because the mat-list-item
doesn't have a disabled
property like the button does, so something like this will NOT work:
<mat-list-item *ngFor="let phase of phases"
[disabled]="!isActive(phase) && !phase.isComplete"
>
But, as mentioned in this answer, you can create a css class to disable mouse events and display the item as disabled, so the code would look like:
<mat-list-item *ngFor="let phase of phases"
[class.disabled]="!isActive(phase) && !phase.isComplete"
>