Kann ich die Schritte eines Matten-Horizontal-Steppers in Angular / Angular Material programmgesteuert verschieben?

86

Ich habe eine Frage zu Angular Material (mit Angular 4+). Angenommen, ich füge in meiner Komponentenvorlage eine <mat-horizontal-stepper>Komponente hinzu und habe in jedem Schritt Schrittschaltflächen <mat-step>zum Navigieren in der Komponente. Wie so ...

<mat-horizontal-stepper>
  <mat-step>
    Step 1
    <button mat-button matStepperPrevious type="button">Back</button>
    <button mat-button matStepperNext type="button">Next</button>
  </mat-step>
  <mat-step>
    Step 2
    <button mat-button matStepperPrevious type="button">Back</button>
    <button mat-button matStepperNext type="button">Next</button>
  </mat-step>
  <mat-step>
    Step 3
    <button mat-button matStepperPrevious type="button">Back</button>
    <button mat-button matStepperNext type="button">Next</button>
  </mat-step>
</mat-horizontal-stepper>

Jetzt frage ich mich, ob es möglich ist, die Schaltflächen aus jedem Schritt zu entfernen und sie an <mat-horizontal-stepper>einer anderen Stelle in einer statischen Position oder sogar außerhalb der zu platzieren, <mat-horizontal-stepper>und ich kann mithilfe von Code in meiner Komponententypskriptdatei hin und her navigieren. Um eine Idee zu geben, möchte ich, dass mein HTML so etwas ist

<mat-horizontal-stepper>
    <mat-step>
        Step 1
    </mat-step>
    <mat-step>
        Step 2
    </mat-step>
    <mat-step>
        Step 3
    </mat-step>
    <!-- one option -->
    <div>
       <button mat-button matStepperPrevious type="button">Back</button>
       <button mat-button matStepperNext type="button">Next</button>
    </div>
</mat-horizontal-stepper>

<!-- second option -->
<div>
   <button (click)="goBack()" type="button">Back</button>
   <button (click)="goForward()" type="button">Next</button>
</div>
Mike Sav
quelle

Antworten:

178

Ja. Es ist möglich, mit der selectedIndexEigenschaft von zu einem bestimmten Schritt zu springen MatStepper. Auch MatSteppermacht öffentliche Methoden next()und previous(). Sie können sie verwenden, um sich hin und her zu bewegen.

In Ihrer Vorlage:

Fügen Sie Ihrem Stepper eine ID hinzu, z #stepper. Übergeben Sie dann in Ihren goBack()und goForward()Methoden die Stepper-ID:

<mat-horizontal-stepper #stepper>
    <!-- Steps -->
</mat-horizontal-stepper>    
<!-- second option -->
<div>
   <button (click)="goBack(stepper)" type="button">Back</button>
   <button (click)="goForward(stepper)" type="button">Next</button>
</div>

.. und in Ihrem Typoskript:

import { MatStepper } from '@angular/material/stepper';

goBack(stepper: MatStepper){
    stepper.previous();
}

goForward(stepper: MatStepper){
    stepper.next();
}

Link zur Stackblitz-Demo .


Sie können auch ViewChildeinen Verweis auf die Schrittkomponente in Ihrem TypeScript abrufen, wie unten gezeigt:

@ViewChild('stepper') private myStepper: MatStepper;

goBack(){
    this.myStepper.previous();
}

goForward(){
    this.myStepper.next();
}

In diesem Fall müssen Sie die Schrittreferenz in der Methode im HTML-Code Ihrer Komponente nicht übergeben. Link zur Demo mit ViewChild


Sie können die Schaltflächen Backund wie Nextfolgt aktivieren / deaktivieren :

<button (click)="goBack(stepper)" type="button" 
        [disabled]="stepper.selectedIndex === 0">Back</button>
<button (click)="goForward(stepper)" type="button" 
        [disabled]="stepper.selectedIndex === stepper._steps.length-1">Next</button>
Faisal
quelle
8
Ich habe nur geschaut ViewChildund gesehen, wie ich auf den Stepper verweisen kann - aber du hast mich geschlagen! Ich liebe die Tatsache, dass Sie auch die Deaktivierungs- / Aktivierungsfunktion hinzugefügt haben! Habe ein paar Punkte!
Mike Sav
ViewChildist auch eine gute Option, um den Stepper zu bekommen. Aber ich würde es vorziehen, einen Ausweis zu übergeben. Ich habe auch ViewChildLösung in der Demo \ o /
Faisal
Hallo Faisal, danke für diese großartige Antwort, eine weitere Hilfe, anstatt ein Formular an mat-step zu übergeben, können wir eckige Komponenten übergeben und dann, abhängig davon, ob diese Komponente gültig ist, zum nächsten mat-step übergehen, wie dies erreicht werden kann , danke
Enthu
Schöne Lösung. Aber wie könnten wir den Bildlaufbereich auf den Inhalt des Steppers und nicht auf den eigentlichen Header beschränken? Wenn Sie eine Menge Inhalt hinzufügen, wird der Header nicht mehr sichtbar angezeigt. Da der Header angibt, wo sich der Benutzer in einem bestimmten Prozess befindet, ist es wichtig, dass der Header unabhängig von der Menge des Inhalts in jedem Schritt sichtbar ist.
Wayne Riesterer
1
Wenn Sie Angular 8 und @ViewChild verwenden, sollten Sie static: false verwenden. @ViewChild('stepper', {static: false}) private myStepper: MatStepper; Per Angular wird dieser Wert in Angular 9+ link
rorvis
29

Zusätzlich zu @ Faisals Antwort ist dies meine Einstellung, den MatStepper zum Springen zu bringen, ohne den Stepper in den Argumenten übergeben zu müssen.

Dies ist hilfreich, wenn Sie mehr Flexibilität bei der Manipulation des Steppers benötigen, z. B. von einem Serviceoder etwas anderem.

HTML:

<div fxLayout="row" fxLayoutAlign="center center" fxLayoutGap="6px">
  <button (click)="move(0)">1st</button>
  <button (click)="move(1)">2nd</button>
  <button (click)="move(2)">3rd</button>
  <button (click)="move(3)">4th</button>
</div>

TS-Datei:

move(index: number) {
    this.stepper.selectedIndex = index;
}

Hier ist die Stackblitz-Demo .

Altus
quelle
21

Wenn Sie programmgesteuert zum nächsten Schritt navigieren möchten und einen linearen Schritt verwenden, führen Sie die folgenden Schritte aus:

  • Erstellen Sie eine steppersolche: <mat-horizontal-stepper linear #matHorizontalStepper>
  • Definieren Sie mat-stepwie folgt :<mat-step [completed]="isThisStepDone">
  • mat-stepErstellen Sie von innen eine Schaltfläche, um zum nächsten Schritt zu gelangen: <button (click)="next(matHorizontalStepper)">NEXT STEP</button>
  • In der .tsDatei deklarieren Sie eine MatStepperReferenz mit dem Namen stepper :
    @ViewChild('matHorizontalStepper') stepper: MatStepper;
  • Innerhalb der .tsDatei initialisieren Sie außerdem isThisStepDoneals false :isThisStepDone: boolean = false;
  • Schreiben Sie dann die Methode für die Schaltfläche NEXT STEP mit dem Namen next():

    submit(stepper: MatStepper) {
     this.isThisStepDone = true;
     setTimeout(() => {           // or do some API calls/ Async events
      stepper.next();
     }, 1);
    }
    
BlackBeard
quelle
3
Der asynchrone Teil ( setTimeout()) wird aufgrund der Zustandsausbreitung über benötigt isThisStepDone.
Yuri
2

Sie können dies auch tun, indem Sie den ausgewählten Index des Steppers mit selectedIndex angeben.

stackblitz: https://stackblitz.com/edit/angular-4rvy2s?file=app%2Fstepper-overview-example.ts

HTML:

<div class="fab-nav-container">
   <mat-vertical-stepper linear="false" #stepper>
       <mat-step *ngFor="let step of stepNodes; let i = index">
           <ng-template matStepLabel>
               <p> {{step.title}} </p>
           </ng-template>
       </mat-step>
   </mat-vertical-stepper>
</div>

<div class="button-container">
   <div class="button-grp">
      <button mat-stroked-button (click)="clickButton(1, stepper)">1</button>
      <button mat-stroked-button (click)="clickButton(2, stepper)">2</button>
      <button mat-stroked-button (click)="clickButton(3, stepper)">3</button>
   </div>
</div>

TS:

import {Component, OnInit, ViewChild} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import { MatVerticalStepper } from '@angular/material';
import { MatStepper } from '@angular/material';
export interface INodes {
    title: string;
    seq: number;
    flowId: string;
}
/**
 * @title Stepper overview
 */
@Component({
  selector: 'stepper-overview-example',
  templateUrl: 'stepper-overview-example.html',
  styleUrls: ['stepper-overview-example.scss'],
})
export class StepperOverviewExample implements OnInit {
  @ViewChild(MatVerticalStepper) vert_stepper: MatVerticalStepper;
  @ViewChild('stepper') private myStepper: MatStepper;

  stepNodes: INodes[] = [
    { title: 'Request Submission', seq: 1, flowId: 'xasd12'}, 
    { title: 'Department Approval', seq: 2, flowId: 'erda23'}, 
    { title: 'Requestor Confirmation', seq: 3, flowId: 'fsyq51'}, 
  ];

  ngOnInit() {
  }
  ngAfterViewInit() {
    this.vert_stepper._getIndicatorType = () => 'number';
  }
  clickButton(index: number, stepper: MatStepper) {
      stepper.selectedIndex = index - 1;
  }
}
M. Laida
quelle
1
Ich benutze nur @ViewChild('stepper') private myStepper: MatStepper;und als this.matStepper.next();in meiner Funktion. Funktioniert perfekt
Max