web-dev-qa-db-ja.com

Angular4 - フォームコントロール用の値アクセサはありません

私は自分の形に少し問題がある。

私はカスタム要素をしました:

<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を追加しようとしましたが成功しませんでした。入力/選択がないからです...しかし、私は何をすべきかわからない。

誰かがカード全体をクリックしたときに私の「タイプ」をformControlにプッシュするために、私のクリックをこのformControlにバインドしたいと思います。出来ますか?

93
jbtd

formControlNameは、 ControlValueAccessor を実装するディレクティブでのみ使用できます。

インターフェースを実装する

それで、あなたが望むことをするためには、 ControlValueAccessor を実装するコンポーネントを作成しなければなりません。それはが以下の3つの関数を実装することを意味します

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

プロバイダを登録する

次に、このディレクティブがControlValueAccessorであることをAngularに伝える必要があります(TypeScriptがJavaScriptにコンパイルされるときにコードから取り除かれるので、インターフェースはそれをカットするつもりはありません)。これを行うには、providerを登録します。

プロバイダは NG_VALUE_ACCESSOR を提供し、 既存の値を使用します 。ここに forwardRef も必要です。 NG_VALUE_ACCESSORマルチプロバイダ であるべきです。

たとえば、カスタムディレクティブの名前がMyControlComponentの場合は、@Componentデコレータに渡されるオブジェクト内の次の行に沿って何かを追加する必要があります。

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

使用法

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

反応型フォーム を使うと、formControlNameを正しく使うことができ、フォームコントロールは期待通りに振る舞います。

リソース

159

私はあなたがinputではなくdivformControlName="surveyType"を使うべきだと思います

40
Vega