Reputation: 571
I have read an article about difference between property and attribute bindings. From what I understood, most of the time, Angular2 prefers property bindings, because after each change in data, the DOM would be updated. (If I am mistaken, please correct me).
I have a custom component and use it from the parent component. In it, I have an @Input
named truevalue
. when I initiate truevalue
from the parent via property binding, sometimes, it does not change. I used following code:
<my-checkbox [(ngModel)]="chkItems" [disabled]="!editMode" [trueValue]="Y"></my-checkbox>
If I send true
or "1"
into trueValue
it works, but If I send "Y"
or "YES"
, it does not work. So I am forced to use attribute binding. I don't know what is the problem.
I have changed it, into the following:
<my-checkbox [(ngModel)]="chkItems" [disabled]="!editMode" trueValue="Y"></my-checkbox>
Thanks in advance
Upvotes: 49
Views: 56356
Reputation: 156524
A couple of others have mentioned this, but I think a good example is important to highlight the difference. Suppose you have some radio buttons that are bound like this:
<div *ngFor="let item of results">
<input type="radio" value="{{item.id}}" name="{{item.id}}" [(ngModel)]="selectedItemId">
</div>
This would appear to work correctly, but if item.id
is a numeric value rather than a string, selectedItemId
would get set to a string value instead of an integer. This could cause defects in unexpected places. For example, using item.id == selectedItemId
might return true when item.id === selectedItemId
would always be false.
So I'd suggest that it's probably a good practice to always use property binding on the value
property, because it's specifically used to store and bind to values rather than just changing the HTML.
<div *ngFor="let item of results">
<input type="radio" [value]="item.id" name="{{item.id}}" [(ngModel)]="selectedItemId">
</div>
Same goes for boolean attributes. Note that in some cases like checked
and disabled
, Angular appears to treat interpolated values as booleans, but in others like hidden
, it doesn't. See this stackblitz for an example.
Upvotes: 10
Reputation: 2379
I came to understand from the following sentences
First I will explain a little bit about html attribute and dom property
For example
<input id="idInput" type="text" value="xyz" />
In console of a browser if we type
idInput.getAttribute('value') //attribute value gives xyz
idInput.value // property value also gives xyz
If we change the input text in textbox to tyz
:
idInput.getAttribute('value') // attribute value gives xyz
idInput.value // property value also gives tyz
Now different types of binding in angular
String Interpolation {{name}}
Property Binding [disabled]="name"
Here [disabled]
is a property of DOM. Not the attribute disabled
found in html.
Attribute Binding attr.colspan ="{{colspanval}}"
When property corresponding to the attribute doesn't exist for example colspan doesn't have corresponding dom property so attribute binding is required.
Error is thrown in console if we try to use colspan = "{{cospanval}}"
- property binding
Upvotes: 36
Reputation: 1673
Property binding([]) and interpolation({{}}) , both are similar and both supports one way data binding(supply data from component to html template).There is a minor difference between them. We must use property binding for non-string data.such as
<div [disabled]='isdissabled'>Text</div>
here is property that is defined inside component.
isdissabled : boolean=true;(after that change it to false in both scenario it would work as expected)
<div disabled='{{isdissabled}}'>Text</div>
but this scenario would not work as expected(both scenario it would be dissabled).
Upvotes: 3
Reputation: 3182
When rendering data values as strings, there is no technical reason to prefer one form to the other.
If we want data values as boolean or other than string then we should go for property binding
Upvotes: 15
Reputation: 2249
Technically there are 3 ways to bind properties.
String Interpolation - {{ expression }} - render the bound value from component's template and it converts this expression into a string.
Property Binding - [target]="expression" - does the same thing by rendering value from component to template, but if you want to bind the expression that is other than string (for example - boolean), then property Binding is the best option.
bind-target="expression" - This is not a regular way of using.
Its always your decision to use whichever option that fits your use case.
Upvotes: 2
Reputation: 657338
Property binding like
[trueValue]="..."
evaluates the expression "..."
and assigns the value
"true"
evaluates to the value true
"Y"
is unknown. There is no internal Y
value in TypeScript and no property in the component class instance, which is the scope of template binding.
In this case you would want
[trueValue]="'Y'"
Note the additional quotes to make Y
a string.
Plain attributes are also assigned to inputs
trueValue="Y"
is plain HTML without any Angular2 binding and attribute values are always strings. Therefore this would assign the string Y
.
Another way is string interpolation
trueValue="{{true}}"
would assign the value "true"
(as string) because the expression withing {{...}}
would be evaluated and then converted to a string before passed to the input.
This can't be used to bind other values than strings.
To explicitly bind to an attribute instead of a property you can use
(besides trueValue="Y"
which creates an attribute but doesn't do any evaluation)
[attr.trueValue]="'Y'"
or
attr.trueValue="{{'Y'}}"
Attribute binding is helpful if you want to use the trueValue
attribute to address the element with CSS selectors.
Upvotes: 59
Reputation: 4359
Assuming my-checkbox
is your custom component selector and you are using this in your parent component.
As you have trueValue
as @Input
property on your custom component, in order to use it in parent component Y
must evaluate to some value
which it does in case of 1 (equivalent to true).
For property-binding to work, it must evaluate to a value. "YES" or "Y" are just string value which will not be evaluated unless you do something like :
export class ParentComponent` {
Y = "YES"; // <--or "Y"
}
and then display trueValue
using interpolation
in your custom component like {{trueValue}}
another thing to note is when you use {{}}
i.e interpolation it always convert the value to .toString()
before binding.
Upvotes: 2