ฉันสามารถย้ายขั้นตอนของ mat-horizontal-stepper ใน Angular / Angular Material โดยทางโปรแกรมได้หรือไม่


88

ฉันมีคำถามเกี่ยวกับ Angular Material (ที่มี Angular 4+) พูดในเทมเพลตองค์ประกอบของฉันฉันเพิ่ม<mat-horizontal-stepper>องค์ประกอบและในแต่ละขั้นตอน<mat-step>ฉันมีปุ่มสเต็ปเปอร์เพื่อนำทางส่วนประกอบ ชอบจัง ...

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

ตอนนี้ฉันกำลังสงสัยว่าเป็นไปได้หรือไม่ที่จะลบปุ่มออกจากแต่ละขั้นตอนและวางไว้ที่อื่นใน<mat-horizontal-stepper>ตำแหน่งคงที่หรือแม้กระทั่งภายนอก<mat-horizontal-stepper>และฉันสามารถนำทางไปข้างหลังและข้างหน้าโดยใช้โค้ดภายในไฟล์ typescript ของคอมโพเนนต์ของฉัน เพื่อให้ความคิดฉันต้องการให้ HTML ของฉันเป็นแบบนี้

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

คำตอบ:


182

ใช่. เป็นไปได้ที่จะข้ามไปยังสเต็ปเปอร์เฉพาะโดยใช้selectedIndexคุณสมบัติของMatStepper. นอกจากนี้ยัง MatStepperเปิดเผยวิธีการสาธารณะnext()และprevious(). คุณสามารถใช้เพื่อเลื่อนไปมา

ในเทมเพลตของคุณ:

#stepperเพิ่มรหัสไปเช่น stepper ของคุณ จากนั้นในgoBack()และgoForward()วิธีการของคุณให้ส่ง 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>

.. และใน typescript ของคุณ:

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

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

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

เชื่อมโยงไปยังสาธิต stackblitz


คุณยังสามารถใช้ViewChildเพื่ออ้างอิงถึงส่วนประกอบ stepper ใน TypeScript ของคุณได้ดังที่แสดงด้านล่าง:

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

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

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

ในกรณีนี้คุณไม่ต้องส่งการอ้างอิง stepper ในวิธีการใน html ของคอมโพเนนต์ของคุณ ลิงก์ไปยังการสาธิตด้วย ViewChild


คุณสามารถเปิด / ปิดปุ่มBackและNextโดยใช้สิ่งต่อไปนี้:

<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
ฉันแค่มองViewChildและดูว่าฉันจะอ้างอิง Stepper ได้อย่างไร - แต่คุณเอาชนะฉันไปแล้ว! ชอบความจริงที่คุณเพิ่มฟังก์ชันปิด / เปิดใช้งานด้วย! มีบางจุด!
Mike Sav

ViewChildยังเป็นตัวเลือกที่ดีในการรับสเต็ปเปอร์ แต่ฉันต้องการส่งรหัส ฉันได้เพิ่มViewChildวิธีแก้ปัญหาในการสาธิต \ o /
Faisal

สวัสดี Faisal ขอบคุณสำหรับคำตอบที่ยอดเยี่ยมเช่นนี้อีกหนึ่งความช่วยเหลือแทนที่จะส่งแบบฟอร์มไปยัง mat-step เราสามารถส่งส่วนประกอบเชิงมุมได้จากนั้นขึ้นอยู่กับส่วนประกอบนั้นว่าถูกต้องฉันสามารถข้ามไปยัง mat-step ถัดไปได้อย่างไร , ขอบคุณ
Enthu

ทางออกที่ดี แต่เราจะ จำกัด พื้นที่การเลื่อนเฉพาะเนื้อหาของ stepper ได้อย่างไรไม่ใช่ส่วนหัวจริง หากคุณเพิ่มเนื้อหาจำนวนมากส่วนหัวจะเลื่อนออกไปจนสุดสายตา เนื่องจากส่วนหัวเป็นตัวบ่งชี้ว่าผู้ใช้อยู่ที่ใดในกระบวนการบางอย่างจึงเป็นสิ่งสำคัญที่จะต้องมองเห็นส่วนหัวโดยไม่คำนึงถึงปริมาณเนื้อหาในแต่ละขั้นตอน
Wayne Riesterer

1
หากคุณใช้ Angular 8 และใช้ @ViewChild คุณควรใช้static: false @ViewChild('stepper', {static: false}) private myStepper: MatStepper; Per Angular ค่านี้จะดีฟอลต์เป็น falseในลิงก์
rorvis

29

นอกจากคำตอบของ@ Faisalแล้วนี่คือสิ่งที่ฉันใช้ในการทำให้ MatStepper กระโดดโดยไม่จำเป็นต้องผ่านสเต็ปเปอร์ในอาร์กิวเมนต์

สิ่งนี้มีประโยชน์เมื่อคุณต้องการความยืดหยุ่นมากขึ้นในการจัดการกับ stepper เช่นจาก a Serviceหรืออย่างอื่น

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 ไฟล์:

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

นี่คือการสาธิต stackblitz


21

หากคุณต้องการนำทางโดยใช้โปรแกรมไปยังขั้นตอนถัดไปและหากคุณใช้ Linear Stepperให้ทำตามขั้นตอนด้านล่าง:

  • สร้างสิ่งstepperนี้: <mat-horizontal-stepper linear #matHorizontalStepper>
  • กำหนดmat-stepดังนี้:<mat-step [completed]="isThisStepDone">
  • จากภายในให้mat-stepสร้างปุ่มเพื่อไปยังขั้นตอนต่อไปดังนี้: <button (click)="next(matHorizontalStepper)">NEXT STEP</button>
  • ใน.tsไฟล์ประกาศการMatStepperอ้างอิงชื่อstepper :
    @ViewChild('matHorizontalStepper') stepper: MatStepper;
  • นอกจากนี้ภายใน.tsไฟล์เริ่มต้นisThisStepDoneเป็นเท็จ :isThisStepDone: boolean = false;
  • จากนั้นเขียนวิธีการสำหรับปุ่มNEXT STEPชื่อnext():

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

3
setTimeout()จำเป็นต้องใช้ส่วน async ( ) เนื่องจากการเผยแพร่สถานะผ่านisThisStepDone.
Yuri

2

คุณสามารถทำได้โดยระบุดัชนีจริงของ stepper โดยใช้ 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
ฉันแค่ใช้@ViewChild('stepper') private myStepper: MatStepper;และมากกว่าthis.matStepper.next();ในฟังก์ชันของฉัน ทำงานได้อย่างสมบูรณ์
สูงสุด
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.