[解決済み] AngularのngDefaultControlとは何ですか?
質問
いいえ、これは重複した質問ではありません。SOとGithubにあるたくさんの質問と問題で、私はこのディレクティブを
[(ngModel)]
ディレクティブがあり、フォームに含まれていない場合。これを追加しないと、エラーが発生します。
ERROR Error: No value accessor for form control with unspecified name attribute
OK、この属性を置けばエラーはなくなる。でも、ちょっと待ってください。誰もこの属性が何をするものなのか知りません! Angularのドキュメントには全く書かれていません。必要ないとわかっているのに、なぜバリューアクセッサが必要なのでしょうか?この属性はバリューアクセサとどう関係しているのでしょうか?このディレクティブは何をするのですか? バリューアクセサーとは何ですか、そしてどのように使うのですか?
そして、なぜ皆、まったく理解できないことをやり続けるのでしょうか。この行を追加すれば動く、ありがとう、こんなの良いプログラムの書き方じゃない。
そして 私が読んだのは、1つではなく
に
Angularのフォームに関する巨大なガイド
と
についてのセクションがあります。
ngModel
:
- https://angular.io/guide/forms
- https://angular.io/guide/reactive-forms
- https://angular.io/guide/template-syntax#ngModel
そして、何を知っていますか?バリューアクセッサや
ngDefaultControl
. どこにあるんだ?
解決方法は?
[ngDefaultControl】を使用します。]
サードパーティーのコントロールには
ControlValueAccessor
を使用すると、angular フォームで機能します。それらの多くは、Polymerの
<paper-input>
のような挙動をします。
<input>
ネイティブ要素を使用することができ、そのため
DefaultValueAccessor
. を追加する
ngDefaultControl
属性があれば、そのディレクティブを使用することができます。
<paper-input ngDefaultControl [(ngModel)]="value>
または
<paper-input ngDefaultControl formControlName="name">
これが、このアトラクションが導入された最大の理由ですね。
というものでした。
ng-default-control
属性
アルファ版のangular2では
.
そこで
ngDefaultControl
のセレクタの1つです。
デフォルト値アクセッサー
ディレクティブを使用します。
@Directive({
selector:
'input:not([type=checkbox])[formControlName],
textarea[formControlName],
input:not([type=checkbox])[formControl],
textarea[formControl],
input:not([type=checkbox])[ngModel],
textarea[ngModel],
[ngDefaultControl]', <------------------------------- this selector
...
})
export class DefaultValueAccessor implements ControlValueAccessor {
どういう意味ですか?
これは、独自の値アクセサを持たない要素(ポリマーコンポーネントなど)にこの属性を適用できることを意味します。つまり、この要素は
DefaultValueAccessor
で、この要素をアンギュラーフォームで使用することができます。
を実装する必要があります。
ControlValueAccessor
ControlValueAccessor
アンギュラー ドキュメントの状態
ControlValueAccessorはAngularフォームAPIの橋渡しとして機能します。 と DOM 内のネイティブな要素との間に存在します。
簡単なangular2アプリケーションで以下のテンプレートを書いてみましょう。
<input type="text" [(ngModel)]="userName">
を理解するために、私たちの
input
上記の動作は、この要素にどのディレクティブが適用されているかを知る必要があります。ここでは、angularがエラーとともにヒントを与えています。
未処理のプロミスが拒否されました。テンプレートパースエラー。にバインドできません。 ngModel' は 'input' の既知のプロパティではないので、'ngModel' を使用します。
さて、SOを開いて答えを出します:import
FormsModule
をあなたの
@NgModule
:
@NgModule({
imports: [
...,
FormsModule
]
})
export AppModule {}
インポートして、すべて意図したとおりに動作するようになりました。しかし、フードの下はどうなっているのでしょうか?
FormsModule は、以下のディレクティブをエクスポートします。
@NgModule({
...
exports: [InternalFormsSharedModule, TEMPLATE_DRIVEN_DIRECTIVES]
})
export class FormsModule {}
いくつかの調査の後、3つのディレクティブが、私たちの
input
1) NgControlStatus
@Directive({
selector: '[formControlName],[ngModel],[formControl]',
...
})
export class NgControlStatus extends AbstractControlStatus {
...
}
2) NgModel
@Directive({
selector: '[ngModel]:not([formControlName]):not([formControl])',
providers: [formControlBinding],
exportAs: 'ngModel'
})
export class NgModel extends NgControl implements OnChanges,
3) デフォルト値アクセサー
@Directive({
selector:
`input:not([type=checkbox])[formControlName],
textarea[formControlName],
input:not([type=checkbox])formControl],
textarea[formControl],
input:not([type=checkbox])[ngModel],
textarea[ngModel],[ngDefaultControl]',
,,,
})
export class DefaultValueAccessor implements ControlValueAccessor {
NgControlStatus
ディレクティブは、以下のようなクラスを操作するだけです。
ng-valid
,
ng-touched
,
ng-dirty
であり、ここでは省略できる。
DefaultValueAccesstor
提供する
NG_VALUE_ACCESSOR
トークンをプロバイダ配列に格納します。
export const DEFAULT_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DefaultValueAccessor),
multi: true
};
...
@Directive({
...
providers: [DEFAULT_VALUE_ACCESSOR]
})
export class DefaultValueAccessor implements ControlValueAccessor {
NgModel
ディレクティブは、コンストラクタに注入されます。
NG_VALUE_ACCESSOR
トークンを使用することで、同じホスト要素で宣言された
export NgModel extends NgControl implements OnChanges, OnDestroy {
constructor(...
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[]) {
私たちの場合
NgModel
を注入します。
DefaultValueAccessor
. そして、NgModel ディレクティブは、共有された
setUpControl
関数を使用します。
export function setUpControl(control: FormControl, dir: NgControl): void {
if (!control) _throwError(dir, 'Cannot find control with');
if (!dir.valueAccessor) _throwError(dir, 'No value accessor for form control with');
control.validator = Validators.compose([control.validator !, dir.validator]);
control.asyncValidator = Validators.composeAsync([control.asyncValidator !, dir.asyncValidator]);
dir.valueAccessor !.writeValue(control.value);
setUpViewChangePipeline(control, dir);
setUpModelChangePipeline(control, dir);
...
}
function setUpViewChangePipeline(control: FormControl, dir: NgControl): void
{
dir.valueAccessor !.registerOnChange((newValue: any) => {
control._pendingValue = newValue;
control._pendingDirty = true;
if (control.updateOn === 'change') updateControl(control, dir);
});
}
function setUpModelChangePipeline(control: FormControl, dir: NgControl): void {
control.registerOnChange((newValue: any, emitModelEvent: boolean) => {
// control -> view
dir.valueAccessor !.writeValue(newValue);
// control -> ngModel
if (emitModelEvent) dir.viewToModelUpdate(newValue);
});
}
そして、実際に橋が架かっている様子がこちらです。
NgModel
制御を設定する
(1)
を呼び出し
dir.valueAccessor !.registerOnChange
メソッドを使用します。
ControlValueAccessor
にコールバックを格納します。
onChange
(2)
プロパティを設定し、このコールバックを起動します。
input
イベント発生
(3)
. そして最後に
updateControl
関数がコールバック内で呼び出されます。
(4)
function updateControl(control: FormControl, dir: NgControl): void {
dir.viewToModelUpdate(control._pendingValue);
if (control._pendingDirty) control.markAsDirty();
control.setValue(control._pendingValue, {emitModelToViewChange: false});
}
angularがフォームAPIを呼び出す場所
control.setValue
.
これが、その仕組みのショートバージョンです。
関連
-
[解決済み】JavaScriptで「無効な日付」のDateインスタンスを検出する
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] JavaScriptでオブジェクトをディープクローンする最も効率的な方法は何ですか?
-
[解決済み] とは何ですか! (not not)演算子とは何ですか?
-
[解決済み] callとapplyの違いは何ですか?
-
[解決済み] セレクトボックスのオプションをすべて削除してから、オプションを1つ追加して、jQueryで選択するにはどうすればよいですか?
-
[解決済み] setTimeout(fn, 0)が役に立つことがあるのはなぜですか?
-
[解決済み] Reactコンポーネントに条件付きで属性を追加するにはどうすればよいですか?
-
[解決済み] Angularでselect要素をオブジェクトにバインドする
-
[解決済み】JavaScript版sleep()とは?)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Heroku:ノードアプリで「このアプリにはデフォルトの言語が検出されませんでした」エラーがスローされる
-
[解決済み】ERROR エラーです。スイッチのname属性が指定されていないフォームコントロールの値アクセッサがない
-
[解決済み】フォームコントロールの値アクセサがない
-
[解決済み】TypeError: 'undefined'はオブジェクトではありません。
-
[解決済み】Javascriptのコールバック関数がFirefoxで「Callback is not a function」というエラーを投げる
-
[解決済み】ある要素を別の要素に移動させるには?
-
[解決済み】エラー:リスン EACCES 0.0.0.0:80 OSx Node.js
-
[解決済み】TypeError: AngularJSで未定義のプロパティ'get'を読み取れない
-
[解決済み】'useState' が定義されていない no-undef React
-
[解決済み】react router v^4.0.0 Uncaught TypeError: 未定義のプロパティ'location'を読み取れない