web-dev-qa-db-ja.com

Angular Material Stepperにより、古いステップに戻るときに、mat-formfieldが動的フォームを検証します

動的フォームを操作するときに、angular Materials mat-stepperで問題が発生しています。たとえば、それぞれが独自のフォームを持つ3つのステップを持つステッパーがあります。ただし、最初のステップでは非表示を使用します。このステップではフォームを動的に追加できるため、フォームを有効かどうかを判断して、すべてのフォームをステップにバインドすることはできません。

最初のステップでは、複数のフォームを作成でき、追加された新しいフォームにランダムな検証が行われることなく、すべてが期待どおりに機能します。この問題は、手順2または3に進み、最初の手順に戻って新しいフォームを作成すると、すべてのフィールドが赤で強調表示されて自動的に開始される場合に発生します。

私は抑制するために多くの異なる試みを試みましたが、私は成功しませんでした。以下は、最初のステップに、ステップコントロールにバインドされたhiddenForm、デフォルトフォーム、およびそのステップでさらにフォームを作成するためのボタンが含まれている基本的な例です。

これを修正しようとする私の研究は、マテリアルステッパーが、新しく追加されたかどうかに関係なく、無効な場合はすべてのマットフォームフィールドを赤にすることを信じるようになりました。

<mat-horizontal-stepper [linear]="true">
    <mat-step [stepControl]="hiddenForm" label="step 1"
      <form [formGroup]="myForm">
        <mat-form-field>
          <mat-label>
            First Name
          </mat-label>

          <input [formControl]="firstName"matInput>

          <mat-error *ngIf="!firstName.valid && firstName.touched">
            First Name required
          </mat-error>
        </mat-form-field>
      </form>

    <button (click)="AddNewForm()">Add New Form</button>
  </mat-step>
</mat-horizontal-stepper>

試行の失敗:(現在のフォームは新しく追加されたフォームです)

this.currentForm.markAsUntouched();
this.currentForm.markAsPristine();
this.currentForm.setErrors(null);
this.currentForm.reset();

this.currentForm.get('firstName).setErrors(null);
this.currentForm.get('firstName).reset();
this.currentForm.get('firstName).markAsPristine();
this.currentForm.get('firstName).markAsUntouched();

<mat-step [completed]="true" ..> ( on all steps )
5
L1ghtk3ira

背景情報

私が見つけた最も良い解決策は、mat-stepperのパラメーターを変更することです。任意の時点で選択されたステップがあります。ステップでは、ステップが操作されたかどうかを変更できます。ステップが以前に訪問された場合、interactedパラメーターはtrueに設定されます。ただし、これは意図された意味であり、すべてのmat-form-fieldsにクラスを追加すると問題が発生し、それらが赤くなります。

これが悪いユーザーエクスペリエンスを引き起こすシナリオ:

  1. 最初のステップを完了して、2番目のステップに進みます。 2番目のステップに進んだ後、最初のステップで間違いを犯したことに気付き、最初のステップに戻ることにしました。変更を加えて、もう一度2番目のステップに進みます。 mat-form-fieldsがある場合はすでにこのステップにアクセスしているため、クラスが追加され(おそらく他の変更)、フォームフィールドがすべて赤になります。これは、ユーザーが技術的に間違いを犯しておらず、過度の負担になる可能性があるため、ユーザーエクスペリエンスが低下します。

  2. 最初のステップでは、動的フォームを作成する場所にそれがあります。簡単にするために、ヒーローの例えのツアーを使用しましょう。最初のステップでは、フォームを動的に追加できます。各フォームは、追加する新しいヒーローを表します。 3人のヒーローを追加し、ステップ2に進みました。ステップ2を完了する前に、いくつかのヒーローを忘れてステップ1に戻ります。[ヒーローの作成]ボタンをクリックすると、動的フォームがポップアップしますが、すべてのmat-form-fieldsは、ユーザーが間違えたように赤になりました。これは、もう1つの貧弱なユーザーエクスペリエンスです。

修正:

hero.stepper.html

<mat-horizontal-stepper [linear]="true" 
  (selectionChange)="stepChanged($event, stepper);">

  <mat-step [stepControl]="hiddenForm" label="step 1"
    <form [formGroup]="heroFormGroupArray[0]">
      <mat-form-field>
        <mat-label>Hero Name</mat-label>

        <input [formControl]="heroName"matInput>

        ...
      </mat-form-field>
    </form>

    <button (click)="AddNewHero()">Add New Hero</button>
  </mat-step>
</mat-horizontal-stepper>

hero.stepper.ts

export class heroStepComponent implements OnInit {
  constructor(){
    ...
  }

  ngOnInit(){
    ...
  }

  stepChanged(event, stepper){
    stepper.selected.interacted = false;
  }
}
9
L1ghtk3ira

前に続く post stepChanged関数のより良い実装を見つけました:

  stepChanged(event: StepperSelectionEvent) {
    if (event.previouslySelectedIndex > event.selectedIndex) {
     event.previouslySelectedStep.interacted = false;
    }
  }

このコードは、前のステップに進むステップにのみ相互作用プロパティを設定します。

1
George Knap