Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ControlValueAccessor with multiple formControl in child component

Tags:

I have multiple formcontrols in the child component, how to apply validators in the child component, So that original form will become invalid. It would be ideal to implement it with ControlValueAccessor but want to start with 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

like image 201
Anonymous Me Avatar asked Nov 09 '16 18:11

Anonymous Me


People also ask

What is Ng_value_accessor?

NG_VALUE_ACCESSOR provider specifies a class that implements ControlValueAccessor interface and is used by Angular to setup synchronization with formControl . It's usually the class of the component or directive that registers the provider.

What is ControlValueAccessor in Angular?

Control Value Accessor is an interface that provides us the power to leverage the Angular forms API and create a communication between Angular Form API and the DOM element. It provides us many facilities in angular like we can create custom controls or custom component with the help of control value accessor interface.


2 Answers

I don't know why the question was down voted, but I feel it may be helpful to other So I am posting the answer. After multiple attempts to bind child's formgroup I was able to successfully bind 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

like image 79
Anonymous Me Avatar answered Sep 22 '22 13:09

Anonymous Me


At first, this helped me a lot, but then I found out, that we're over-complicating things. We do not have to build our own formControl, we can just pass the formGroup to our child component. In the parent component, instead of

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

we initialize 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 a Input Property for the 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

Building your own formControl is really an overkill here, for more information about that, have a look here: http://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html

like image 23
Benny Avatar answered Sep 20 '22 13:09

Benny