ControlValueAccessor with multiple formControl in child component

I have several forms of control in a child component, how to apply validators in a child component, so that the original form will become invalid. It would be ideal to implement it with ControlValueAccessor, but you need to start with a simple @input form group.

@Component({ selector: 'my-child', template: ' <h1>Child</h1> <div [formGroup]="childForm"> <input formControlName="firstName"> <input formControlName="lastName"> </div> ' }) export class Child { @Input() childForm: FormGroup; } 

http://plnkr.co/edit/K1xAak4tlUKtZmOV1CAQ

+7
source share
3 answers

I don’t know why the question was rejected, but I feel this may be useful to others, so I am posting the answer. After several attempts to link the child form of the group, I was able to successfully link the value

  @Component({ selector: 'my-child', template: ' <h1>Child</h1> <div [formGroup]="name"> <input formControlName="firstName"> <input formControlName="lastName"> </div> ', providers: [ {provide: NG_VALUE_ACCESSOR, useExisting: Child, multi: true} ] }) export class Child implements ControlValueAccessor { name: FormGroup; constructor(fb: FormBuilder) { this.name = fb.group({ firstName:[''], lastName: [''] }); } writeValue(value: any) { if(value) { this.name.setValue(value); } } registerOnChange(fn: (value: any) => void) { this.name.valueChanges.subscribe(fn); } registerOnTouched() {} } 

http://plnkr.co/edit/ldhPf7LTFVtTFHe9zfAj?p=preview

+9
source

At first it helped me a lot, but then I found out that we complicate things too much. We do not need to create our own formControl, we can just pass formGroup to our child component. In the parent component instead

 this.form = fb.group({ name:['Angular2 (Release Candidate!)'], username: [{firstName: 'First', lastName: 'Last'}], email:['My Email'] }); 

we initialize the username as a FormGroup instead of a control:

 this.form = fb.group({ name:['Angular2 (Release Candidate!)'], username: fb.group({ firstName: ['First'], lastName: ['Last'] }), email:['My Email'] }); 

In the child component, we need an input property for FormGroup

 @Input() usernameGroup: FormGroup; 

In the child template:

 <div [formGroup]="usernameGroup"> <input formControlName="firstName"> <input formControlName="lastName"> </div> 

and then in the parent template:

 <my-child [usernameGroup]="form.controls.username"></my-child> 

For more information, check out this post: https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2

Creating your own formControl is really redundant, for more information on this, see here: http://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html

+4
source

What you want to do can be achieved more easily without implementing a ControlValueAccessor. Instead, you can simply set viewProviders in the child component to use the existing parent NgForm as the ControlContainer.

Then there is no need to pass form / formGroup as an input parameter to the child component, as the form controls will automatically become part of the parent form.

child.component.ts:

 @Component({ selector: 'child', templateUrl: './child.component.html', viewProviders: [{ provide: ControlContainer, useExisting: NgForm}] }) export class Child { @Input() firstName; @Input() lastName; } 

input-child.component.html:

 <h1>Child</h1> <div> <input [(ngModel)]="firstName" name="firstname"> <input [(ngModel)]="lastName" name="lastname"> </div> 

parent.component.html:

 <form #personalForm="ngForm" name="personalForm"> <child [firstName]="firstName" [lastName]="lastName"></child> </form> 
+1
source

Source: https://habr.com/ru/post/1259520/


All Articles