Sharing what worked for me:
Adding an input to the Angular 4 app
Assuming that we have 2 components:
parent-component
child-component
We wanted to pass some value from parent-component to child-component i.e. an @Input from parent-component.html to child-component.ts. Below is an example which explains the implementation:
parent-component.html looks like this:
<child-component [someInputValue]="someInputValue"></child-component>
parent-component.ts looks like this:
class ParentComponent {
someInputValue = 'Some Input Value';
}
child-component.html looks like this:
<p>Some Input Value {{someInputValue}}</p>
child-component.ts looks like this:
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'child-component',
templateUrl: './child-component.html'
})
export class ChildComponent implements OnInit {
@Input() someInputValue: String = "Some default value";
@Input()
set setSomeInputValue(val) {
this.someInputValue += " modified";
}
constructor() {
console.log('someInputValue in constructor ************** ', this.someInputValue); //someInputValue in constructor ************** undefined
}
ngOnInit() {
console.log('someInputValue in ngOnInit ************** ', this.someInputValue); //someInputValue in ngOnInit ************** Some Input Value
}
}
Notice that the value of the @Input value is available inside ngOnInit() and not inside constructor().
Objects reference behaviour in Angular 2 / 4
In Javascript, objects are stored as references.
This exact behaviour can be re-produced with the help of Angular 2 / 4. Below is an example which explains the implementation:
parent-component.ts looks like this:
class ParentComponent {
someInputValue = {input: 'Some Input Value'};
}
parent-component.html looks like this:
{{someInputValue.input}}
child-component.html looks like this:
Some Input Value {{someInputValue}}
change input
child-component.ts looks like this:
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'child-component',
templateUrl: './child-component.html'
})
export class ChildComponent implements OnInit {
@Input() someInputValue = {input:"Some default value"};
@Input()
set setSomeInputValue(val) {
this.someInputValue.input += " set from setter";
}
constructor() {
console.log('someInputValue in constructor ************** ', this.someInputValue); //someInputValue in constructor ************** undefined
}
ngOnInit() {
console.log('someInputValue in ngOnInit ************** ', this.someInputValue); //someInputValue in ngOnInit ************** Some Input Value
}
changeInput(){
this.someInputValue.input += " changed";
}
}
The function changeInput() will change the value of someInputValue inside both ChildComponent & ParentComponent because of their reference. Since, someInputValue is referenced from ParentComponent's someInputValue object - the change in ChildComponent's someInputValue object changes the value of ParentComponent's someInputValue object. THIS IS NOT CORRECT. The references shall never be changed.