I am stuck on trying to pass a property value into my component. From what I've read everything looks correct. But it is still not working. My test value gets output to the screen and the console as null. :(
This is my test component:
import {Component, Input} from 'angular2/angular2';
@Component({
selector: 'TestCmp',
template: `Test Value : {{test}}`
})
export class TestCmp {
@Input() test: string;
constructor()
{
console.log('This if the value for user-id: ' + this.test);
}
}
This is how I am calling the component from the parent page.
<TestCmp [test]='Blue32'></TestCmp>
When the page render's the test value is empty. I only see 'Test Value :'.
Instead of 'Test Value : Blue32'.
You have four things that I can note :
[test]
. That means that angular2 is looking for a variable named Blue32
instead of passing a raw string.So with a few fixes it should work
Example updated to beta 1
import {Component, Input} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
@Component({
selector : 'childcmp',
template: `Test Value : {{test}}`
})
class ChildCmp {
@Input() test: string;
ngOnInit() {
console.log('This if the value for user-id: ' + this.test);
}
}
@Component({
selector: 'testcmp',
template : `<childcmp [test]="'Blue32'"></childcmp>`
directives : [ChildCmp]
})
export class TestCmp {}
bootstrap(TestCmp);
See this plnkr as an example.
I see that people still reach this answer, so I've updated the plnkr to beta 1 and I corrected one point on the explanation : You can access inputs in ngAfterViewInit, but you can access them earlier in the lifecycle within ngOnInit.
It's that easy as surrounding the string with double quotes, like this:
<TestCmp [test]="'Blue32'"></TestCmp>
If you use brackets [] the Angular uses property binding and expects to receive an expression inside the quotes and it looks for a property called 'Blue32' from your component class or a variable inside the template.
If you want to pass string as a value to the child component you can pass it like so:
<child-component childProperty='passing string'></child-component>
or if you for some reason want to have the brackets:
<child-component [childProperty]="'note double quotes'"></child-component>
And then take it in to child.component.ts like this:
import { Component, Input } from "@angular/core";
@Component({})
export class ChildComponent {
@Input()
childProperty: string;
}
This angular class could make the trick for static attributes: ElementRef https://angular.io/docs/ts/latest/api/core/index/ElementRef-class.html
import {ElementRef} from 'angular2/core'
constructor(elementRef: ElementRef) {
elementRef.nativeElement.getAttribute('api')
}
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.
I believe that the problem here might have to do with the page's life cycle. Because inside the constructor the value of this.test is null. But if I add a button to the template linked to a function that pushes the value to the console (same as I am doing in the constructor) this.test will actually have a value.
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