2016-10-06 7 views
8

Ich versuche, eine datengesteuerte Form, mit Eingängen von einer anderen Komponente, wie diese kommen zu bauen:Angular 2 - Form Gruppenkomponente

<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> 

Die app-form-group Komponente etwas wird wie folgt aussehen:

<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> 

Das Problem ist, dass formControlName eine formGroup Richtlinie muss daher bekomme ich diesen Fehler:

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). 

Gibt es eine Möglichkeit, dieses Problem zu umgehen?

+0

Sie benötigen, um Ihre eigene 'ControlValueAccessor' zu implementieren, wie hier geführt http://blog.thoughtram.io/angular/2016/07/27/custom-form-controls- in-angular-2.html –

Antwort

4

Sie Ihre FormGroup [formGroup]="signupForm" in app-form-group Component.You verwenden sollten diesen Code verwenden können:

<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

Wie kann 'signupForm' aus der untergeordneten Komponente' app-form-group' sichtbar sein? Brauchen Sie es nicht wie in der Antwort von Bernhard Hochgatterer? – Javarome

+0

Sie müssen "Signuoform" als Eingabe senden –

3

Sie können eine @Input Eigenschaft verwenden, um die Referenz in die Unterkomponente zu erhalten:

app- form-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> 

App-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> 

Ausführliche Informationen haben einen Blick auf dieses Tutorial: https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2

1

Wenn Sie eine benutzerdefinierte Komponente für die Datenbindung an einen einzelnen Wert implementieren möchten Die richtige Winkelmethode hierfür ist die Vorgehensweise, bei der die übergeordnete Ansicht entweder [formControl] oder [formControlName] angibt.

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

In Ihrem Kind Kontrolle müssen Sie Folgendes tun:

Zuerst fügen Sie den folgenden Anbieter auf Ihre @Component Erklärung, so Angular Ihre Komponente kennt [formControlName]/[formControl]

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

Die Klasse Ihrer untergeordneten Komponente muss dann die Schnittstelle ControlValueAccessor implementieren. Diese sollte ein voll funktionierendes Beispiel sein, wenn nicht dann lassen Sie mich wissen, und ich werde den Code ändern, tippte ich es direkt in den Browser.

@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; 
    } 
} 

Ihre app-form-group Vorlage wäre so etwas wie dieses

<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. hinzufügen [formGroup]="signupForm" jedem Ihrer app-form-group Instanzen in der Hauptansicht sehen
  2. OnInit Implementieren in Ihrer app-form-group Kontrolle.
  3. hinzufügen private controlContainer: ControlContainer an den Konstruktor Ihrer app-form-group Komponente so Angular es
  4. hinzufügen public form: FormGroup; Eigenschaft auf Ihre app-form-group Komponente injizieren.
  5. In ngOnInit fügen Sie den folgenden Code

    this.form = this.containerControl.control;

In Ihrer app-form-group Vorlage würden Sie hinzufügen [formGroup] wie so

Mit dieser Methode ist, dass die geringste Menge an Code erfordert, und ist das, was ich empfehlen würde, wenn Sie einbetten möchten Composite-Steuerelemente, die mehrere Datenelemente bearbeiten (wie eine Adresse).

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

Verwandte Themen