web-dev-qa-db-ja.com

Angular:NgFormからカスタム入力コンポーネントでmarkAsDirty()を呼び出す

NgModelを使用して入力のラッパーであるカスタムコンポーネントを実装しました。それらをControlValueAccessorに接続しました。それはうまく機能し、親コンポーネントから値に簡単にアクセスできます。

しかし、markAsDirty()を呼び出そうとすると、タッチされたフラグがコンポーネントでのみ変更され、コンポーネント内の入力には影響しません。例を挙げましょう。

// Parent Component
onSubmit(form: NgForm) {
    this.form.controls.registerEmail.markAsDirty();
}

// Thats how the component looks like in my form:
<form #form="ngForm" (ngSubmit)="onSubmit(form)" [ngClass]="{'has-error': !form.valid}">
    <form-text label="E-Mail" name="registerEmail" email required placeholder="" [(ngModel)]="eMail"></form-text>
</form>

// Result
<form-text label="E-Mail" name="registerEmail" class="ng-untouched ng-invalid ng-dirty">
    <label for="form-text-2">E-Mail</label>
    <input class="input-control invalid ng-untouched ng-pristine ng-invalid" type="text" id="form-text-2">
</form-text>

フォームテキストに「ng-dirty」クラスがあることがわかるように、内部の入力は元のままです。

私のカスタムコンポーネントを実装するために、私はあなたがウェブで見つける多くの指示を使用しました。これが私が使用したものです: 検証json入力を備えたangular2カスタムフォームコントロール

送信ボタンが押されたときに、すべての入力フィールドをダーティとしてマークしたい。私の検証が表示されるので、入力をぼかします。

私のコンポーネントがControlValueAccessorから継承する問題があることがわかりました。コンポーネントとNgFormの間の唯一の接続は、そのNgModelを介したものです。 NgFormには独自のNgModelがあるため、私のコンポーネントをFormControlとして使用できます。イベントでは、2つの方向に値を渡すことができます。しかし、それはmarkAsDirty()やmarkAsTouched()のようなメソッドでは不可能です。コンポーネント内では問題ありません。しかし、私のNgFormはコンポーネントに実際にアクセスできません。 NgModelのみ。

それを実装する方法はありますか?それを理解することはそれほど難しいことではないと私は思いましたが、私はそれと長い間苦労しています。当面の唯一の解決策は、jQueryを使用してすべての入力を反復処理し、フォーカスを発生させることです。そのためのよりクリーンなソリューションが必要です。

どうも

11
bndamm

フォームのControlValueAccessordirtyプロパティを実装するコンポーネントに入力として渡し、ReactiveFormsModuleFormControlを使用して内部入力の状態を更新できます。 。

フォームを保持するコンポーネント:

<form #myForm="ngForm" (submit)="onSubmit($event)">
    <my-input name="my-input" [(ngModel)]="myInput" [formDirty]="myForm.dirty"></my-input>
    <button type="submit">Submit</button>
</form>

次に、ControlValueAccessorを実装するコンポーネントで:

  ngOnChanges({ formDirty }: SimpleChanges) {
    if (formDirty.currentValue) {
      this.inputCtrl.markAsDirty();
    } else {
      this.inputCtrl.markAsPristine();
    }
  }

ここに関連するスニペットがあります

1
Korte

問題は、ダーティ状態が変化したときに通知を取得する簡単な方法がないことです。 https://github.com/angular/angular/issues/10887 を参照してください。

ヘルパーディレクティブ:

@Directive({
  selector: 'my-input'
})
export class MagickDirective implements DoCheck {
  constructor(private control:NgModel){
  }
  ngDoCheck(): void {
    //you can do whatever you want
    if(this.control.dirty) {
      (this.control.valueAccessor as MyInputComponent).setDirty(true);
    }
  }
}
0
kemsky

コントロールのステータスをタッチに設定する場合は、コンポーネント内からonTouched()(this._onTouchedCallback)を呼び出す必要があります。これも同じです。_onChangeCallback

たとえば、my-custom-inputのinputタグに(ngModelChange)= "onTouched(value)"を追加することにより

コピー元: https://github.com/angular/angular/issues/10151

0
Zoltán Rajkai