In a simplified way I have an Angular2 Component and an input object like this:
class MyObject{
Prop1:string;
Prop2:Number;
}
@Component()
export class MyComponent{
@Input() myObject: MyObject;
DoSomethingIfProp1Change(){
console.log(myObject.Prop1);
}
}
How can I detect if Prop1 was changed from Hostcomponent and then execute the DoSomethingIfProp1Change method from inside MyComponent?
Use the ngOnChanges() lifecycle method in your component. ngOnChanges is called right after the data-bound properties have been checked and before view and content children are checked if at least one of them has changed.
Whenever there is a change in the object, the subscribe method is called, so you should manually run the change detector inside the subscribe method to update the view. To run the change detector manually: Inject ChangeDetectorRef service in the component.
ngOnChanges gets called before ngOnInit and whenever a component's bound input is changed FROM THE PARENT COMPONENT. Remember that ngOnChanges is specific to bound inputs on the component. This means if you don't have any @Input properties on a child, ngOnChanges will never get called.
In fact, by default Angular2 detects changes when object reference is updated not its content. But this default behavior can be changed by using the DoCheck
interface.
In your case (detecting that a property was updated into the myObject
object, you could use the following approach:
@Component({
selector: 'my-component',
(...)
})
export class MyComponent implements DoCheck {
@Input() myObject: MyObject;
differ: any;
constructor(differs: KeyValueDiffers) {
this.differ = differs.find([]).create(null);
}
ngDoCheck() {
var changes = this.differ.diff(this.myObject);
if (changes) {
changes.forEachChangedItem((elt) => {
if (elt.key === 'prop1') {
this.doSomethingIfProp1Change();
}
});
}
}
doSomethingIfProp1Change() {
console.log('doSomethingIfProp1Change');
}
}
When the value of the prop1
property is updated, the doSomethingIfProp1Change
method is called.
See this plunkr: http://plnkr.co/edit/uvOKMXQa9Ik8EiIhb60Y?p=preview.
You can use observables to support notification of subscribers. Angular itself doesn't provide support for observing changes of internal object state.
class MyObject{
constructor() {
this.prop1Change$ = new Observable(observer =>
this._prop1Observer = observer).share(); // share() allows multiple subscribers
this.prop2Change$ = new Observable(observer =>
this._prop2Observer = observer).share();
console.debug(this._prop2Observer);
}
prop1Change$: Observable<string>;
private _prop1Observer: Observer;
_prop1:string;
get prop1():string { return this._prop1 };
set prop1(value:string) {
this._prop1 = value;
this._prop1Observer && this._prop1Observer.next(value);
}
prop1Change$: Observable<number>;
private _prop2Observer: Observer;
_prop2:Number;
get prop2():number { return this._prop2 };
set prop2(value:number) {
this._prop2 = value;
console.debug(this);
this._prop2Observer && this._prop2Observer.next(value);
}
}
This code could be shortened by using Subject
but Observable
should be favored over Subject
.
@Component()
export class MyComponent{
@Input() myObject: MyObject;
count2:number;
DoSomethingIfProp1Change(){
console.log(myObject.prop1);
}
ngOnChanges(changes: {[propName: string]: SimpleChange}) {
console.log('changes');
if(changes['myObject']) {
if(this.prop2Subscription) {
this.prop2Subscription.unsubscribe();
}
this.prop2Subscription = this.myObject.prop2Change$.subscribe(value => {
this.count2 = value;
console.log('count2: ' + value);
});
// same for `prop2`
}
}
}
Plunker example
See also Delegation: EventEmitter or Observable in Angular2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With