Reputation: 174
I have BusinessComponent
(parent) and AddressComponent
(child). Now within the AddressComponent
, the two way data binding is working fine. Now I require any change in AddressComponent
to be emitted to the BusinessComponent
as an Address
object, not an individual property of the Address
object. I tried using ngOnChanges()
but the doc says this.
Angular only calls the hook when the value of the input property changes. The value of the hero property is the reference to the hero object. Angular doesn't care that the hero's own name property changed. The hero object reference didn't change so, from Angular's perspective, there is no change to report!
And without emitting the data, the parent is detecting the changes of AddressComponent
. I couldn't find a way to achieve this.
Here are my code samples.
AddressComponent
import { Component, EventEmitter, Input, OnInit, Output, OnChanges, SimpleChanges } from '@angular/core';
import { AppService } from '../services';
import { Address } from '../types';
@Component({
selector: 'app-address',
templateUrl: 'address.component.html'
})
export class AddressComponent implements OnInit, OnChanges {
@Input()
address: Address;
@Output()
addressChange: EventEmitter<Address> = new EventEmitter<Address>();
constructor(
private appService: AppService
) { super(appService); }
ngOnInit() {
this.address = new Address('');
}
ngOnChanges(changes: SimpleChanges) {
// This is not being called for emitting the changes.
console.log(changes);
this.addressChange.emit(this.address);
}
}
AddressComponent Template
<div class="form-row">
<label class="form-label" for="houseNo">{{ labels['houseNo'] }}</label>
{{ address.houseNo }}
<input [(ngModel)] = "address.houseNo" type="text" name="houseNo" id="houseNo" ref-houseNo>
</div>
<div class="form-row">
<label class="form-label" for="street">{{ labels['street'] }}</label>
<input [(ngModel)] = "address.street" type="text" name="street" id="street" ref-street>
</div>
<div class="form-row">
<label class="form-label" for="village">{{ labels['village'] }}</label>
<input [(ngModel)] = "address.village" type="text" name="village" id="village" ref-village>
</div>
<div class="form-row">
<label class="form-label" for="city">{{ labels['city'] }}</label>
<input [(ngModel)] = "address.city" type="text" name="city" id="city" ref-city>
</div>
And I bind the input like this in BusinessComponet
<app-address [(address)]="address"></app-address>
.
How to achieve this?
Upvotes: 4
Views: 4040
Reputation: 73367
As mentioned in comments, you do not need the two way binding or @Output
. Since JS objects are mutable, means that reference is same object, BUT, you are doing
ngOnInit() {
this.address = new Address('');
}
in child, which initialization I do not also understand, since Address
(I assume it's a class) has several properties. But if you want to have the same reference you shouldn't do that.
I suggest you use interface for your Address
, something like:
export interface Address {
houseNo: number;
street: string;
village: string;
city: string;
}
also then you can type your object like:
address: Address = {}
in your parent, or then set initial values to it, but seems you want a clean object in your child.
So remove the following from child OnInit
and you should be good to go :)
this.address = new Address('');
Upvotes: 1