formを作るときに何気なく使っているformControlNameですが、ふと本家のソースを読んでみたら、普段使わないような記法が出てきたので調べてみました。
今回はHostデコレーターに注目します。
環境
- angular 2.3.1
- angular/material 2.0.0-beta.2
シンプルなフォーム
とりあえずinputが一つあるだけの簡単なフォームを作成します
コード例
simple-form.component.ts
@Component({...})
export class SimpleFormComponent {
form: FormGroup;
constructor(
private fb: FormBuilder
) {
this.form = this.fb.group({
user: ['default user name'],
});
}
onSubmit() {
console.log(this.form.value);
}
}
simple-form.component.html
<md-card>
<md-card-title>SimpleForm</md-card-title>
<md-card-content>
<form [formGroup]="form" novalidate (ngSubmit)="onSubmit()">
<md-input-container>
<input mdInput formControlName="user">
</md-input-container>
<p>{{ form.get('user').value }}</p>
<div>
<button md-button>Submit</button>
</div>
</form>
</md-card-content>
</md-card>
material使っちゃったので見づらいですが、formGroupを作り、userプロパティにformControlがセットされただけのシンプルなフォームです。
formControlNameのソースを見る
constructor(
@Optional() @Host() @SkipSelf() parent: ControlContainer,
ソースを眺めると、なんとなくformGroupを参照してそうな雰囲気です。
Hostデコレーター
any directive that matches the type between the current element and the Shadow DOM root.
DOMを辿って宣言した型に該当する要素を参照できると。
すごい。なんでもやれそうな気がしてきますね。
formGroupから、特定のformControlを取得するDirectiveを書いてみる
Hostアノテーションを用いることによって、formGroupが取得出来そうなので、formGroupの取得および、指定されたプロパティの値をログに出すようなDirectiveを書いてみます。
コード例
fake-form-control-name.directive.ts
@Directive({
selector: '[appFakeFormControlName]'
})
export class FakeFormControlNameDirective implements AfterContentInit {
@Input('appFakeFormControlName') appFakeFormControlName: string;
private parent: FormGroupDirective;
constructor(
@Host() parent: FormGroupDirective
) {
this.parent = parent;
}
ngAfterContentInit() {
console.log(
this.parent.form.get(this.appFakeFormControlName).value
);
}
}
この状態で動かすと、コンソールに 'default user name' が流れるのが確認できました