Выделите элемент боковой панели в соответствии с прогрессом

У меня есть боковая панель для отображения хода выполнения задания. Сейчас у меня три фазы.

фазы

В начале проект еще не запущен, поэтому я хочу, чтобы все элементы боковой панели были выделены серым цветом. Я хочу, чтобы текущая фаза основывалась на завершении предыдущих фаз. С правой стороны есть три кнопки. Вот логика.

  1. Работаем над этапом 1. Когда я работаю над этапом 1, элемент боковой панели «Фаза 1» активен и имеет зеленый цвет. Элементы фазы 2 и фазы 3 по-прежнему неактивны.
  2. Работаем над этапом 2. Когда я нажимаю кнопку «Фаза 1 завершена», мы переходим к фазе 2, Фаза 2 окрашивается в зеленый цвет, а Фаза 1 все еще активна, но не имеет цвета.
  3. Работаем над этапом 3. Когда я нажимаю кнопку завершения фазы 2, мы переходим к фазе 3, фаза 3 окрашена в зеленый цвет, а фаза 1 и фаза 2 активны, но не имеют цвета.
  4. Когда мы переходим к следующему этапу, элементы предыдущего этапа имеют видимые границы.

Мой код ТС:

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');
  }
}

Мой 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>

Вот пример стека.

Мои вопросы. Когда я нажимаю кнопки, элемент боковой панели не становится серым по условию. Также я не уверен, как применить зеленый цвет к рабочей фазе.

Наконец, у меня есть много элементов вместо 3 элементов в примере. Я не хочу вручную устанавливать логические значения в событиях кликов.

Обновление:

Правильная редактируемая ссылка stackblitz https://stackblitz.com/edit/angular-material-with-angular-sidenav-etrylt


person Hello    schedule 24.02.2021    source источник
comment
не могли бы вы поделиться ссылкой на редактирование StackBlitz, чтобы образец можно было легко разветвить?   -  person BizzyBob    schedule 25.02.2021
comment
@BizzyBob, прости. Я обновил вопрос, ссылка stackblitz.com/edit/   -  person Hello    schedule 25.02.2021


Ответы (2)


Похоже, вам просто нужна простая структура для представления ваших фаз со свойством, указывающим, завершена она или нет.

interface Phase {
    id: number;
    name: string;
    isComplete: boolean;
}

Затем, когда вы нажимаете кнопку, переключайте свойство isComplete.

Вы можете определить массив из Phase объектов и использовать *ngFor для повторения их в своем шаблоне. Это предотвратит рост вашего шаблона при добавлении дополнительных фаз.

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 }
  ];

боковая панель.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>

Затем вы можете использовать это свойство isComplete в своем шаблоне, чтобы отключить кнопки для уже завершенных фаз:

[disabled]="phase.isComplete"

Вы также можете сделать небольшую вспомогательную функцию, чтобы определить, активна фаза или нет, чтобы отобразить зеленый цвет фона:

public isActive(phase: Phase) {
    // the first incomplete phase found is active
    const activePhase = this.phases.find(p => !p.isComplete);
    return phase.id === activePhase?.id;
}

Затем просто добавьте [class.green]="isActive(phase)" к mat-list-item (при условии, что вы определили класс с именем green в CSS).

Вот рабочий StackBlitz

Теперь отключение элементов навигации для фаз, которые еще не были активны, требует немного больше работы, потому что mat-list-item не имеет свойства disabled, как кнопка, поэтому что-то вроде этого НЕ будет работать:

<mat-list-item *ngFor="let phase of phases" 
               [disabled]="!isActive(phase) && !phase.isComplete"
>

Но, как упоминалось в этом ответе, вы можете создать класс css для отключения событий мыши и отображения элемента как отключенного, поэтому код будет выглядеть так:

<mat-list-item *ngFor="let phase of phases" 
               [class.disabled]="!isActive(phase) && !phase.isComplete"
>
person BizzyBob    schedule 25.02.2021
comment
Спасибо за ваш вклад. Я мог бы четко сформулировать свой вопрос. Если это так, извините за это. Я хочу, чтобы цвет левого элемента (или вкладки) менялся вместе с развитием фаз. Правые боковые кнопки не должны меняться. - person Hello; 25.02.2021
comment
Без проблем! Просто удалите бит, который я добавил к элементу кнопки [disabled]="phase.isComplete". Образец в настоящее время применяет зеленый цвет к левой вкладке. - person BizzyBob; 25.02.2021
comment
Это нормально, я хочу, чтобы незавершенный элемент слева был выделен серым цветом. Есть ли у кода функция? - person Hello; 25.02.2021
comment
Вы можете изменить определение класса .disabled, чтобы он имел серый цвет или что вам нужно :-) - person BizzyBob; 25.02.2021
comment
К вашему сведению: я обновил stackblitz, чтобы включить серый цвет. У вас это сработало? - person BizzyBob; 25.02.2021

person    schedule
comment
боковая ширина = 10; фаза: любая = {актив1: ложь, актив2: ложь, актив3: ложь, }; CompletePhase: строка [] = []; - person Rahul Prajapati; 25.02.2021
comment
onPhase(type: string) { if (this.phase[type] !== undefined) { for (let key in this.phase) { this.phase[key] = false; } this.phase[type] = true; если (this.completedPhase.indexOf(type) === -1) { this.completedPhase.push(type); } } } - person Rahul Prajapati; 25.02.2021
comment
Можете ли вы отформатировать свой код с отступом? Это трудно читать. Если бы вы могли редактировать в StackBlize, было бы здорово. Спасибо. - person Hello; 25.02.2021