Property and Attribute Binding
The plant card needs a photo whose address comes from data, a button that turns grey while watering is in progress, and a red border when the plant is thirsty. Each of these sets something on an element. That is the job of square brackets.
The rule
Brackets mean "evaluate this"; no brackets means "this exact text".
Property binding puts the result of an expression into a DOM property, or into a component input:
<img [src]="plant().photo" [alt]="plant().name" />
<button [disabled]="watering()">Water</button>
<app-plant-card [plant]="p" />Without brackets, src="plant().photo" is plain HTML: the browser gets the literal characters plant().photo as the address.
Two handy shapes for styling:
<article [class.thirsty]="isThirsty()">...</article>
<div class="gauge" [style.width.%]="waterLevel()"></div>[class.thirsty] adds the class while the expression is true and removes it when false. [style.width.%] sets one style, with the unit written after the dot.
Attribute binding exists because not every HTML attribute has a DOM property. ARIA attributes, data-* attributes and many SVG attributes are like this. Prefix the name with attr.:
<button [attr.aria-label]="'Water ' + plant().name">💧</button>
<li [attr.data-plant-id]="plant().id">...</li>If the bound value is null, Angular removes the attribute completely, which is how you make one optional.
Why the difference? An HTML attribute is the starting text in the markup; a DOM property is the live value on the element object. disabled has a property, so [disabled] works. data-plant-id has no property at all, so [data-plant-id] fails with "not a known property", and [attr.data-plant-id] fixes it. (Recent Angular versions also accept ARIA names without the prefix, but [attr.aria-label] works in every version and says plainly that you are setting an attribute.)
The shortcut
Ask two quick questions. Is the value computed? Then use brackets. Is it ARIA, data-* or SVG? Then add attr.. Everything else is a plain [property].
Computed?
The badge text colour depends on
isThirsty(), so it needs brackets.
Drills
Answer fast — trust the rule.
What does the browser receive for <img src="plant().photo" />?
Which binding disables the button while watering() is true?
How do you set a data-plant-id attribute from plant().id?
What happens with [attr.data-note]="note()" when note() returns null?
Remember
[prop]="expr"evaluates and sets a DOM property or component input; no brackets means literal text.[class.x]toggles a class,[style.width.px]sets one style,[attr.x]sets a real attribute.- Trap:
data-*(and, for older versions, ARIA) attributes needattr.; bindingnullremoves the attribute.
