【问题标题】:Can I programmatically move the steps of a mat-horizontal-stepper in Angular / Angular Material我可以在 Angular / Angular Material 中以编程方式移动 mat-h​​orizo​​ntal-stepper 的步骤吗
【发布时间】:2018-03-10 04:51:36
【问题描述】:

我有一个关于 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>

现在我想知道是否可以从每个步骤中删除按钮并将它们放在 &lt;mat-horizontal-stepper&gt; 的其他位置的静态位置,甚至在 &lt;mat-horizontal-stepper&gt; 之外,我可以使用我的代码中的代码来回导航组件打字稿文件。给出一个想法,我希望我的 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>

【问题讨论】:

    标签: angular angular-material angular-material2


    【解决方案1】:

    是的。可以使用MatStepperselectedIndex 属性跳转到特定的步进器。此外,MatStepper 公开了公共方法 next()previous()。您可以使用它们来回移动。

    在您的模板中:

    为您的步进器添加一个 id,例如#stepper。然后在您的goBack()goForward() 方法中,传递步进器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>
    

    .. 在你的打字稿中:

    import { MatStepper } from '@angular/material/stepper';
    
    goBack(stepper: MatStepper){
        stepper.previous();
    }
    
    goForward(stepper: MatStepper){
        stepper.next();
    }
    

    链接到stackblitz demo


    您还可以使用ViewChild 来获取对 TypeScript 中步进器组件的引用,如下所示:

    @ViewChild('stepper') private myStepper: MatStepper;
    
    goBack(){
        this.myStepper.previous();
    }
    
    goForward(){
        this.myStepper.next();
    }
    

    在这种情况下,您不必在组件的 html 中的方法中传递步进器引用。链接到Demo with ViewChild


    您可以使用以下方法启用/禁用BackNext 按钮:

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

    【讨论】:

    • 我只是在看ViewChild,看看我如何引用步进器——但你已经打败了我!喜欢您也添加了禁用/启用功能的事实!给点分数吧!
    • ViewChild 也是获取步进器的好选择。但我更喜欢传递一个id。我还在演示中添加了ViewChild 解决方案\o/
    • 嗨 Faisal 感谢您提供如此好的答案,还有一个帮助,我们可以传递角度组件,而不是传递表单到 mat-step,然后根据该组件是否有效,我可以遍历到下一个 mat -step,如何实现,谢谢
    • 不错的解决方案。但是我们怎么能将滚动区域限制为步进器的内容而不是实际的标题。如果您添加大量内容,则标题将滚动到视线之外。由于标题指示了用户在某个进程中的位置,因此无论每个步骤中的内容量如何,标题都可见是很重要的。
    • 如果你使用 Angular 8,并且使用 @ViewChild,你应该使用 static: false @ViewChild('stepper', {static: false}) private myStepper: MatStepper; Per Angular,这个值将默认为 false i> 在 Angular 9+ link
    【解决方案2】:

    除了@Faisal 的回答之外,这是我在不需要在参数中传递步进器的情况下使 MatStepper 跳转的看法。

    当您需要更灵活地操作步进器时,这很有帮助,例如来自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 demo

    【讨论】:

      【解决方案3】:

      如果您想以编程方式导航到下一步,并且如果您使用线性步进器,请按照以下步骤操作:

      • 像这样创建stepper&lt;mat-horizontal-stepper linear #matHorizontalStepper&gt;

      • 像这样定义mat-step&lt;mat-step [completed]="isThisStepDone"&gt;

      • mat-step 内部创建一个按钮以进入下一步,如下所示:&lt;button (click)="next(matHorizontalStepper)"&gt;NEXT STEP&lt;/button&gt;

      • .ts 文件中声明一个名为stepperMatStepper 引用:
        @ViewChild('matHorizontalStepper') stepper: MatStepper;

      • 另外,在.ts 文件中将isThisStepDone 初始化为falseisThisStepDone: boolean = false;

      • 然后为名为@9​​87654333@的NEXT STEP按钮编写方法:

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

      注意:异步部分 (setTimeout()) 是必需的,因为通过 isThisStepDone 进行状态传播。

      【讨论】:

      • 由于通过isThisStepDone 进行状态传播,因此需要异步部分 (setTimeout())。
      • Thnks bruh,这就是我一直在寻找的……对于线性步进器。
      【解决方案4】:

      您也可以通过使用 selectedIndex 指定步进器的实际索引来实现。

      堆栈闪电战: 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;
        }
      }
      

      【讨论】:

      • 我只是在我的函数中使用@ViewChild('stepper') private myStepper: MatStepper; 而不是this.matStepper.next();。完美运行
      【解决方案5】:

      如果你在子组件内部,你可以注入步进器。

      MyMainPageWithStepper.html (simplified)
      
      <mat-horizontal-stepper>
        <mat-step label="Upload">
          <my-component></my-component>
        </mat-step>
      </mat-horizontal-stepper>
      
      MyComponent.ts
      
      constructor(private readonly _stepper: CdkStepper}{}
      
      someFunction(): void {
         this._stepper.next();
      }
      

      【讨论】:

        猜你喜欢
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        • 2020-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-07
        • 2018-04-23
        相关资源
        最近更新 更多