Posso spostare programmaticamente i passaggi di un tappetino orizzontale in materiale angolare / angolare


88

Ho una domanda riguardante Angular Material (con Angular 4+). Diciamo che nel mio modello di componente aggiungo un <mat-horizontal-stepper>componente e all'interno di ogni passaggio<mat-step> sono presenti pulsanti stepper per navigare nel componente. Così...

<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>

Ora mi chiedo se sia possibile rimuovere i pulsanti da ogni passaggio e averli altrove <mat-horizontal-stepper>in una posizione statica o addirittura al di fuori di <mat-horizontal-stepper>e posso navigare avanti e indietro utilizzando il codice all'interno del mio file di dattiloscritto del componente. Per dare un'idea, vorrei che il mio HTML fosse qualcosa del genere

<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>

Risposte:


182

Sì. È possibile passare a uno stepper specifico utilizzando la selectedIndexproprietà di MatStepper. Inoltre, MatStepperespone metodi pubblici next()e previous(). Puoi usarli per spostarti avanti e indietro.

Nel tuo modello:

Aggiungi un ID al tuo stepper es #stepper. Poi, nel tuo goBack()e goForward()metodi, passare l'ID passo-passo:

<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>

.. e nel tuo dattiloscritto:

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

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

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

Link alla demo di Stackblitz .


Puoi anche utilizzare ViewChildper ottenere un riferimento al componente stepper nel tuo TypeScript come mostrato di seguito:

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

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

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

In questo caso, non è necessario passare il riferimento stepper nel metodo nell'html del componente. Collegamento alla demo con ViewChild


È possibile abilitare / disabilitare i pulsanti Backe Nextutilizzando quanto segue:

<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>

8
Stavo solo guardando ViewChilde vedendo come avrei potuto fare riferimento allo Stepper, ma mi hai battuto! Adoro il fatto che tu abbia aggiunto anche la funzionalità di disabilitazione / abilitazione! Avere alcuni punti!
Mike Sav,

ViewChildè anche una buona opzione per ottenere lo stepper. Ma preferirei passare un documento d'identità. Ho anche aggiunto una ViewChildsoluzione nella demo \ o /
Faisal

Ciao Faisal, grazie per questa ottima risposta, un altro aiuto, invece di passare un modulo a mat-step possiamo passare componenti angolari e poi, a seconda che quel componente sia valido, posso passare al successivo mat-step, come si può ottenere , grazie
Enthu

Bella soluzione. Ma come potremmo limitare l'area di scorrimento solo al contenuto dello stepper e non all'intestazione effettiva. Se aggiungi un mucchio di contenuti, l'intestazione scorrerà fuori dalla vista. Poiché l'intestazione fornisce un'indicazione di dove si trova l'utente in un processo, è importante che l'intestazione sia visibile indipendentemente dalla quantità di contenuto in ogni passaggio.
Wayne Riesterer

1
Se stai usando Angular 8 e @ViewChild, dovresti usare static: false @ViewChild('stepper', {static: false}) private myStepper: MatStepper; Per Angular, questo valore diventerà di default false nel collegamento
rorvis

29

Oltre alla risposta di @ Faisal , questa è la mia opinione su come far saltare MatStepper senza dover passare lo stepper negli argomenti.

Questo è utile quando hai bisogno di maggiore flessibilità nel manipolare lo stepper, ad esempio da un Serviceo qualcos'altro.

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>

File TS:

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

Ecco la demo di stackblitz .


21

Se desideri navigare in modo programmatico al passaggio successivo e se stai utilizzando uno stepper lineare , segui i passaggi seguenti:

  • Crea un steppersimile: <mat-horizontal-stepper linear #matHorizontalStepper>
  • Definisci in mat-stepquesto modo:<mat-step [completed]="isThisStepDone">
  • Dall'interno mat-stepcreare un pulsante per andare al passaggio successivo come questo: <button (click)="next(matHorizontalStepper)">NEXT STEP</button>
  • Nel .tsfile dichiarare un MatStepperriferimento denominato stepper :
    @ViewChild('matHorizontalStepper') stepper: MatStepper;
  • Inoltre, all'interno del .tsfile inizializza isThisStepDonecome falso :isThisStepDone: boolean = false;
  • Quindi scrivi il metodo per il pulsante NEXT STEP denominato next():

    submit(stepper: MatStepper) {
     this.isThisStepDone = true;
     setTimeout(() => {           // or do some API calls/ Async events
      stepper.next();
     }, 1);
    }
    

3
La parte asincrona ( setTimeout()) è richiesta a causa della propagazione dello stato tramite isThisStepDone.
Yuri

2

Puoi anche farlo specificando l'indice effettivo dello stepper usando selectedIndex.

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

1
Sto solo usando @ViewChild('stepper') private myStepper: MatStepper;e quindi this.matStepper.next();nella mia funzione. Funziona perfettamente
Max
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.