16

I have ParentComponent and a ChildComponent, and I need to pass the ngModel in ParentComponent to ChildComponent.

// the below is in ParentComponent template
<child-component [(ngModel)]="valueInParentComponent"></child-component>

how can I get the value of ngModel in ChildComponent and manipulate it?

Ibraheem Al-Saady
  • 854
  • 3
  • 14
  • 30
  • You can make an @Input() on the child component, and than inject it from the parent – Denko Mancheski Dec 27 '16 at 19:00
  • I've made a detailed answer to a similar question here: https://stackoverflow.com/questions/40806779/angular-2-large-scale-application-forms-handling/56375605#56375605 – maxime1992 Jun 07 '19 at 13:19

3 Answers3

24

You need to implement ControlValueAccessor in the child class. It's what defines your component as "having a value" that can be bound to using the angular way.

Read more about it here: http://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html

Amit
  • 4,274
  • 21
  • 25
  • 2
    Everywhere I looked, it seemed that I found a solution that required strong coupling using an onChange event in the parent, the entire time knowing there had to be a way to create a component that didn't need any of that. I upvote you with all of my lion's heart. – Chad McGrath Mar 01 '18 at 15:41
2

For Parent -> Child, use @Input

For Child -> Parent, use @Output

So to use both:

In the Parent Component

Typescript:

  onValueInParentComponentChanged(value: string) {
    this.valueInParentComponent = value;
  }

Html

<child-component 
 (onValueInParentComponentChanged)="onValueInParentComponentChanged($event)"
 [valueInParentComponent]="valueInParentComponent">
</child-component>

In the Child Component

Typescript:

export class ChildComponent {  
   @Input() valueInParentComponent: string;
   @Output() onValueInParentComponentChanged = new EventEmitter<boolean>();
} 

onChange(){
  this.onValueInParentComponentChanged.emit(this.valueInParentComponent);
}

Html

<input type="text" [(ngModel)]="valueInParentComponent"   
    (ngModelChange)="onChange($event)"/>

Full Example

https://plnkr.co/edit/mc3Jqo3SDDaTueNBSkJN?p=preview

Other ways to accomplish this:

https://angular.io/docs/ts/latest/cookbook/component-communication.html

Sumama Waheed
  • 3,579
  • 3
  • 18
  • 32
1

It sounds like you are trying to wrap a form control. I wrote a library that helps you do that! s-ng-utils has a superclass to use for your parent component: WrappedFormControlSuperclass. You can use it like this:

@Component({
  template: `
    <!-- anything fancy you want in your parent template -->
    <child-component [formControl]="formControl"></child-component>
  `,
  providers: [provideValueAccessor(ParentComponent)],
})
class ParentComponent extends WrappedFormControlSuperclass<ValueType> {
  // This looks unnecessary, but is required for Angular to provide `Injector`
  constructor(injector: Injector) {
    super(injector);
  }
}

This assumes that <child-component> has a ControlValueAccessor, as @Amit's answer suggests. If you are writing <child-component> yourself, there is also a superclass in s-ng-utils to help with that: FormControlSuperclass.

Eric Simonton
  • 5,702
  • 2
  • 37
  • 54