1. ホーム
  2. javascript

[解決済み] Angular4 - フォームコントロールの値アクセサがない

2022-02-17 10:09:39

質問

カスタム要素を持っています。

<div formControlName="surveyType">
  <div *ngFor="let type of surveyTypes"
       (click)="onSelectType(type)"
       [class.selected]="type === selectedType">
    <md-icon>{{ type.icon }}</md-icon>
    <span>{{ type.description }}</span>
  </div>
</div>

formControlNameを追加しようとすると、エラーメッセージが表示されます。

ERROR Error: No value accessor for form control with name: 'surveyType'

を追加しようとしたのですが ngDefaultControl が、うまくいきません。 input/selectがないのが原因のようですが...どうしたらいいのでしょうか?

このformControlにクリックをバインドして、誰かがカード全体をクリックすると、私の「タイプ」がformControlに押し出されるようにしたいのですが、どうすればいいですか?可能でしょうか?

解決方法は?

を使用することができます。 formControlName を実装しているディレクティブにのみ適用されます。 ControlValueAccessor .

インターフェイスの実装

というわけで、やりたいことをやるには、以下のような実装をしたコンポーネントを作る必要があります。 ControlValueAccessor ということは 以下の3つの機能を実装しています。 :

  • writeValue (モデルからビューに値を書き込む方法をAngularに伝える)
  • registerOnChange (ビューが変更されたときに呼び出されるハンドラ関数を登録します。)
  • registerOnTouched (コンポーネントがタッチイベントを受け取ったときに呼び出されるハンドラを登録します。コンポーネントがフォーカスされたかどうかを知るのに便利です。)

プロバイダを登録する

次に、このディレクティブをAngularに伝える必要があります。 ControlValueAccessor (インターフェースはTypeScriptからJavaScriptにコンパイルされる際にコードから取り除かれるため、カットされることはない)。これを行うには プロバイダを登録する .

プロバイダは、以下のものを提供する必要があります。 NG_VALUE_ACCESSOR 既存の値を使用する . また forwardRef をここに記述します。なお NG_VALUE_ACCESSOR マルチプロバイダ .

例えば、カスタムディレクティブの名前が MyControlComponent である場合、以下の行を @Component デコレータを使用します。

providers: [
  { 
    provide: NG_VALUE_ACCESSOR,
    multi: true,
    useExisting: forwardRef(() => MyControlComponent),
  }
]

使用方法

コンポーネントを使用する準備ができました。とは テンプレート駆動型フォーム , ngModel バインディングが正しく動作するようになりました。

とともに リアクティブフォーム を適切に使用できるようになりました。 formControlName で、フォームコントロールは期待通りの動作をするようになります。

リソース