Reputation: 4050
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
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
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
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