When to use square brackets [ ] in directives @Inputs and when not?
Solution 1:
When you use []
to bind to an @Input()
, it's basically a template expression.
The same way displaying {{abc}}
wouldn't display anything (unless you actually had a variable called abc
).
If you have a string @Input()
, and you want to bind it to a constant string, you could bind it like this: [myText]=" 'some text' "
, or in short, like a normal HTML attribute: myText="some text"
.
The reason [myEnabled]="true"
worked is because true
is a valid template expression which of course evaluates to the boolean true
.
Solution 2:
If you write <img [src]="heroImageUrl">
it means that the right-hand side heroImageUrl
is a template expression.
The simple difference between [myText]="abc"
and myText="abc"
is that in former you are asking angular to set the target PROPERTY myText using the template expression abc
, while in the latter you setting the target property called myText using the string 'abc'.
Let's understand a little more about HTML.
In HTML you can define an element like this.
<input type="text" value="Bob">
input is an element whose attributes
are type and value. When your browser parses this, it will create a DOM entry (an object) for this element. The DOM entry will have some properties
like align, baseURI, childNodes, children etc. So, that's the difference between HTML attributes and DOM properties See reference. Sometimes the attribute and property have same names which causes confusion. For above input tag, it has the attribute value
= Bob and also has a property value
that will have the value of whatever you type in the text box. In summary, attribute is what you define about the tag, and property is what gets generated in the DOM tree.
In the world of Angular, the only role of attributes is to initialize element and possibly directive state. When you write a data binding, you're dealing exclusively with properties and events of the target object. HTML attributes effectively disappear.
So to summarize, in <div [myDirective]="myDefaultText" [myEnabled]="true" [myText]="abc"></div>
you essentially are saying that:
- apply the directive
myDirective
to my div element. - bind the variable
myEnabled
to the expression on the right. The expression saystrue
, so the value of myEnabled is true. - bind the variable
myText
to the expression on the right. The expression saysabc
. Is there any abc defined? No, so the expression evaluated to undefined.
Solution 3:
The brackets tell Angular to evaluate the template expression. If you omit the brackets, Angular treats the string as a constant and initializes the target property with that string. It does not evaluate the string!
Don't make the following mistake:
<!-- ERROR: HeroDetailComponent.hero expects a
Hero object, not the string "currentHero" -->
<hero-detail hero="currentHero"></hero-detail>
check: https://angular.io/docs/ts/latest/guide/template-syntax.html#!#property-binding
Solution 4:
binding []
is for objects, without it the value is string. Be careful about types.
In the code
<div [myDirective]="myDefaultText" [myEnabled]="true" [myText]="abc"></div>
you have tried to bind the object, but the object is not available, thus it's value is undefined
. On the other hand if you remove binding then the object is gone, you have only a string
value assigned to the property.