2016-10-06 11 views
8

私はこのように、別のコンポーネントからの入力で、データ駆動型フォームを構築しようとしている:角度2 - フォームグループコンポーネント

<form [formGroup]="signupForm" (ngSubmit)="onSubmit()"> 
    <app-form-group [name]="name"></app-form-group> 
    <app-form-group [name]="email"></app-form-group> 
    <app-form-group [name]="other"></app-form-group> 
</form> 

app-form-groupコンポーネントは次のようになります

<div class="form-group"> 
    <label class="col-md-2 control-label">{{Name}}</label> 
    <div class="col-md-9"> 
    <input class="form-control" [name]="name" [formControlName]="formCtrlName"> 
</div> 

問題は、したがって、私はこのエラーを取得し、formControlNameformGroupディレクティブを必要としていることである。

Error : Error in ./FormGroupComponent class FormGroupComponent - inline template:3:58 caused by: formControlName must be used with a parent formGroup directive.You'll want to add a formGroup 
    directive and pass it an existing FormGroup instance (you can create one in your class). 

この問題を回避する方法はありますか?

+0

http://blog.thoughtram.io/angular/2016/07/27/custom-form-controls- in-angular-2.html –

答えて

4
このコードを使用することができます app-form-group Component.YouであなたのFormGroup [formGroup]="signupForm"を使用する必要があり

:サブコンポーネントへの参照を取得するために

<div class="form-group" [formGroup]="signupForm"> 
    <label class="col-md-2 control-label">{{Name}}</label> 
    <div class="col-md-9"> 
    <input class="form-control" [name]="name" [formControlName]="formCtrlName"> 
</div> 
+0

'app-form-group'子コンポーネントから' signupForm'をどのように見ることができますか? Bernhard Hochgattererの答えのように明示的に渡す必要はありませんか? – Javarome

+0

"Signuoform"を入力として送信する必要があります –

3

あなたは@Inputプロパティを使用することができます。

APP-フォームgroup.ts:

@Input('group') 
public signupForm: FormGroup; 

app.html:

<form [formGroup]="signupForm" (ngSubmit)="onSubmit()"> 
    <app-form-group [name]="name" [group]="signupForm"></app-form-group> 
    <app-form-group [name]="name" [group]="signupForm"></app-form-group> 
    <app-form-group [name]="name" [group]="signupForm"></app-form-group> 
</form> 

アプリ-フォームgroup.html:

<div class="form-group" [formGroup]="signupForm"> 
    <label class="col-md-2 control-label">{{Name}}</label> 
    <div class="col-md-9"> 
    <input class="form-control" [name]="name" [formControlName]="formCtrlName"> 
</div> 

詳細な情報については、このチュートリアルを見て:https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2

1

あなたは、個々の値へのデータバインディングのためのカスタムコンポーネントを実装したい場合にはそれを行うための正しい角度の方法は、親ビューが[formControl]または[formControlName]のいずれかを指定するアプローチにすることです。あなたが次のことを行う必要があり、あなたの子コントロールに

<app-form-group formControlName="name"></app-form-group> 
<app-form-group formControlName="email"></app-form-group> 
<app-form-group formControlName="other"></app-form-group> 

まずその角度は、あなたのコンポーネントが[formControlName]/[formControl]

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

で動作することができます知っている、あなたの@Component宣言に次のプロバイダを追加子コンポーネントのクラスは、ControlValueAccessorインターフェイスを実装する必要があります。このでなければなりません。私に知らせておかなければコードを変更し、ブラウザに直接入力します。

@Component({ 
    // Ensure [formControl] or [formControlName] is also specified 
    selector: '[formControl] app-form-group, [formControlName] app-form-group', 
    templateUrl: './country-selector.component.html', 
    styleUrls: ['./country-selector.component.scss'], 
    providers: [ 
    { 
     // Provide the value accessor 
     provide: NG_VALUE_ACCESSOR, 
     useExisting: forwardRef(() => CountrySelectorComponent), 
     multi: true 
    } 
    ] 
}) 
export class CountrySelectorComponent implements ControlValueAccessor { 
    private value: any; 
    private hasHadFocus = false; 
    private hasNotifiedTouched = false; 
    private propagateChange: any =() => {}; 
    private propogateTouched: any =() => {}; 

    public changed(event: any) { 
    this.value = event.srcElement.value; 
    this.propagateChange(this.value); 
    } 

    /** 
    * Called when (focus) is triggered 
    */ 
    public focused() { 
    this.hasHadFocus = true; 
    } 

    /** 
    * Called when (blur) is triggered 
    */ 
    public blurred() { 
    if (this.hasHadFocus && !this.hasNotifiedTouched) { 
     // Only notify once, and only if lost focus after a focus 
     this.hasNotifiedTouched = true; 
     this.propogateTouched(); 
    } 
    } 

    /** 
    * Called when a new value is set via code 
    * @param obj 
    */ 
    writeValue(obj: any): void { 
    this.value = obj; 
    } 

    /** 
    * Register a call back to call when our value changes 
    * @param fn 
    */ 
    registerOnChange(fn: any): void { 
    this.propagateChange = fn; 
    } 

    /** 
    * Register a call back to call when our value is first touched 
    * @param fn 
    */ 
    registerOnTouched(fn: any): void { 
    this.propogateTouched = fn; 
    } 
} 

あなたapp-form-groupテンプレートは、あなたのメインビュー

  • があなたのapp-form-groupコントロールでのOnInitを実装するには、あなたのapp-form-groupインスタンスのそれぞれに[formGroup]="signupForm"を追加し、この

    <div class="form-group"> 
        <label class="col-md-2 control-label">{{Name}}</label> 
        <div class="col-md-9"> 
        <input class="form-control" (blur)="blurred()" focus="focussed()" change="changed($event)"> 
    </div> 
    
    1. ようになります。
    2. 角度はそれが
    3. あなたapp-form-groupコンポーネントにpublic form: FormGroup;プロパティを追加注入しますので、あなたのapp-form-groupコンポーネントのコンストラクタにprivate controlContainer: ControlContainerを追加します。 ngOnInitで
    4. 次のコード

      this.formを= this.containerControl.controlを加えます。そう

      これは、コードの最低額を必要とする方法であり、そしてあなたが埋め込みたいときに私が推薦する1であるように[formGroup]追加することになり、あなたのapp-form-groupテンプレートで

    複数のデータ(アドレスなど)を編集する複合コントロール。このブログから

    - >https://mrpmorris.blogspot.co.uk/2017/08/angular-composite-controls-formgroup-formgroupname-reactiveforms.html

    ここに導かれたとしてあなたがあなた自身の `ControlValueAccessor`を実装する必要があります