Deniss M.
Deniss M.

Reputation: 4050

Angular (4): pass a class object from child to parent component

I can pass a class object like Person into a child component from parent component without any problems. But I would like to also manipulate that object in child component and pass it back to parent component.

This is the child component class:

export class ActionPanelComponent {
  @Input('company') company: Company;
  @Output() notify: EventEmitter = new EventEmitter();

  constructor() {
  }

  public deleteCompany() {
    console.log('display company');
    console.log(this.company);
    // FIXME: Implement Delete
    this.company = new Company();
  }

  public onChange() {
    this.notify.emit(this.company);
  }

}

This is the html of this component (excerpt):

<div class="row" (change)="onChange()">
  <div class="col-xs-2">
    <button md-icon-button >
      <md-icon>skip_previous</md-icon>
    </button>
  </div>

This is the parent component class (excerpt):

  public onNotify(company: Company):void {
    this.company = company;
  }

And the parent component html (excerpt):

<action-panel [company]="company" (notify)="onNotify($event)"></action-panel>

I am doing something wrong because I cannot pass my company object inside the .emit and nothing works.

What is the correct way of achieving two way object binding between components? Thanks in advance!

Upvotes: 4

Views: 13864

Answers (3)

Yogesh Sanchihar
Yogesh Sanchihar

Reputation: 1118

It is a workaround that worked for me, if it is helpful for anyone.

Your parent parent-component.ts would be like;

import { Component, OnInit, Input } from '@angular/core';

@Component({
selector: 'parent',
templateUrl:'./parent.component.html',
styleUrls: ['./parent.component.css']
})
export class Parent implements OnInit {

let parentInstance= this; //passing instance of the component to a variable
constructor() { }

parentMethod(var:<classtyepyourchoice>){
console.log(var);
}



 ngOnInit() {
 }



}

In you parent.component.html, you would have your child

 <child [parent]="parentInstance" ></child>

This object will be available in the child component

Now, in your child component you will receive this like

import { Component, OnInit, Input } from '@angular/core';

@Component({
selector: 'child',
templateUrl:'./child.component.html',
styleUrls: ['./child.component.css']
})
export class Child implements OnInit {

@Input('parent') parent;
constructor() { }

childMethod(yourClassObject){
this.parent.parentMethod(yourClassObject);
}



 ngOnInit() {
 }



}

Thus, you can pass classobject from your child, like this, it worked for me.

Upvotes: 1

Aleics
Aleics

Reputation: 51

You were missing the type on the initialization of the EventEmitter.

You could use the Output binding to implement the two way object binding:

Child component (ts)

export class ActionPanelComponent {
    @Input('company') company: Company;
    @Output() companyChange: EventEmitter = new EventEmitter<Company>();

    constructor() {
    }

    public deleteCompany() {
       console.log('display company');
       console.log(this.company);
       // FIXME: Implement Delete
       this.company = new Company();
    }

    public onChange() {
       this.companyChange.emit(this.company);
    }

}

Parent component (html)

<action-panel [(company)]="company"></action-panel>

So like this you don't need to declare an extra function onNotify. If you do need the onNotify function, use another name for the output binding:

export class ActionPanelComponent {
    @Input('company') company: Company;
    @Output() notify: EventEmitter = new EventEmitter<Company>();

    constructor() {
    }

    public deleteCompany() {
       console.log('display company');
       console.log(this.company);
       // FIXME: Implement Delete
       this.company = new Company();
    }

    public onChange() {
       this.notify.emit(this.company);
    }

}

Upvotes: 5

Arg0n
Arg0n

Reputation: 8423

Change it like this to tell TS which Type the EventEmitter should emit:

export class ActionPanelComponent {
  @Input('company') company: Company;
  @Output() notify = new EventEmitter<Company>(); //<---- On this line!

  constructor() {
  }

  public deleteCompany() {
    console.log('display company');
    console.log(this.company);
    // FIXME: Implement Delete
    this.company = new Company();
  }

  public onChange() {
    this.notify.emit(this.company);
  }
}

Upvotes: 3

Related Questions