Attribute binding in Angular helps you set values for attributes directly.
With attribute binding, you can improve accessibility, style your application dynamically, and manage multiple CSS classes or styles simultaneously.
See the
live example
/ download example
for a working example containing the code snippets in this guide.
Prerequisites
link
Property Binding
Syntax
link
Attribute binding syntax resembles property binding, but instead of an element property between brackets, you precede the name of the attribute with the prefix
attr
, followed by a dot.
Then, you set the attribute value with an expression that resolves to a string.
When the expression resolves to
null
or
undefined
, Angular removes the attribute altogether.
Binding ARIA attributes
link
One of the primary use cases for attribute binding is to set ARIA attributes.
To bind to an ARIA attribute, type the following:
src/app/app.component.html
<!-- create and set an aria attribute for assistive technology --><buttontype="button" [attr.aria-label]="actionName">{{actionName}} with Aria</button>
Binding to
colspan
link
Another common use case for attribute binding is with the
colspan
attribute in tables. Binding to the
colspan
attribute helps you to keep your tables programmatically dynamic. Depending on the amount of data that your application populates a table with, the number of columns that a row spans could change.
To use attribute binding with the
<td>
attribute
colspan
Specify the
colspan
attribute by using the following syntax:
[attr.colspan]
.
Set
[attr.colspan]
equal to an expression.
In the following example, you bind the
colspan
attribute to the expression
1 + 1
.
Sometimes there are differences between the name of property and an attribute.
colspan
is an attribute of
<td>
, while
colSpan
with a capital "S" is a property.
When using attribute binding, use
colspan
with a lowercase "s".
For more information on how to bind to the
colSpan
property, see the
colspan
and
colSpan
section of Property Binding.
What’s next
link
Class & Style Binding
Last reviewed on Mon May 02 2022
Angular - Attribute directives
Attribute directives
link
Building an attribute directive
Applying an attribute directive
Handling user events
Passing values into an attribute directive
Setting the value with user input
Binding to a second property
Deactivating Angular processing with
NgNonBindable
Change the appearance or behavior of DOM elements and Angular components with attribute directives.
See the
live example
/ download example
for a working example containing the code snippets in this guide.
Building an attribute directive
link
This section walks you through creating a highlight directive that sets the background color of the host element to yellow.
To create a directive, use the CLI command
ng generate directive
.
ng generate directive highlight
The CLI creates
src/app/highlight.directive.ts
, a corresponding test file
src/app/highlight.directive.spec.ts
, and declares the directive class in the
AppModule
.
The CLI generates the default
src/app/highlight.directive.ts
as follows:
To use the
HighlightDirective
, add a
<p>
element to the HTML template with the directive as an attribute.
src/app/app.component.html
<pappHighlight>Highlight me!</p>
Angular creates an instance of the
HighlightDirective
class and injects a reference to the
<p>
element into the directive's constructor, which sets the
<p>
element's background style to yellow.
Handling user events
link
This section shows you how to detect when a user mouses into or out of the element and to respond by setting or clearing the highlight color.
The
@Input()
decorator adds metadata to the class that makes the directive's
appHighlight
property available for binding.
In
app.component.ts
, add a
color
property to the
AppComponent
.
src/app/app.component.ts (class)
exportclassAppComponent{
color ='yellow';}
To simultaneously apply the directive and the color, use property binding with the
appHighlight
directive selector, setting it equal to
color
.
src/app/app.component.html (color)
<p [appHighlight]="color">Highlight me!</p>
The
[appHighlight]
attribute binding performs two tasks:
Applies the highlighting directive to the
<p>
element
Sets the directive's highlight color with a property binding
Setting the value with user input
link
This section guides you through adding radio buttons to bind your color choice to the
appHighlight
directive.
Add markup to
app.component.html
for choosing a color as follows:
src/app/app.component.html (v2)
<h1>My First AttributeDirective</h1><h2>Pick a highlight color</h2><div><inputtype="radio"name="colors" (click)="color='lightgreen'">Green
<inputtype="radio"name="colors" (click)="color='yellow'">Yellow
<inputtype="radio"name="colors" (click)="color='cyan'">Cyan
</div><p [appHighlight]="color">Highlight me!</p>
Revise the
AppComponent.color
so that it has no initial value.
src/app/app.component.ts (class)
exportclassAppComponent{
color ='';}
In
highlight.directive.ts
, revise
onMouseEnter
method so that it first tries to highlight with
appHighlight
and falls back to
red
if
appHighlight
is
undefined
.
Serve your application to verify that the user can choose the color with the radio buttons.
Binding to a second property
link
This section guides you through configuring your application so the developer can set the default color.
Add a second
Input()
property to
HighlightDirective
called
defaultColor
.
src/app/highlight.directive.ts (defaultColor)
@Input() defaultColor ='';
Revise the directive's
onMouseEnter
so that it first tries to highlight with the
appHighlight
, then with the
defaultColor
, and falls back to
red
if both properties are
undefined
.
To bind to the
AppComponent.color
and fall back to "violet" as the default color, add the following HTML.
In this case, the
defaultColor
binding doesn't use square brackets,
[]
, because it is static.
src/app/app.component.html (defaultColor)
<p [appHighlight]="color"defaultColor="violet">
Highlight me too!
</p>
As with components, you can add multiple directive property bindings to a host element.
The default color is red if there is no default color binding.
When the user chooses a color the selected color becomes the active highlight color.
Deactivating Angular processing with
NgNonBindable
link
To prevent expression evaluation in the browser, add
ngNonBindable
to the host element.
ngNonBindable
deactivates interpolation, directives, and binding in templates.
In the following example, the expression
{{ 1 + 1 }}
renders just as it does in your code editor, and does not display
2
.
src/app/app.component.html
<p>Use ngNonBindable to stop evaluation.</p><pngNonBindable>This should not evaluate: {{ 1 + 1 }}</p>
Applying
ngNonBindable
to an element stops binding for that element's child elements.
However,
ngNonBindable
still lets directives work on the element where you apply
ngNonBindable
.
In the following example, the
appHighlight
directive is still active but Angular does not evaluate the expression
{{ 1 + 1 }}
.
src/app/app.component.html
<h3>ngNonBindable with a directive</h3><divngNonBindable [appHighlight]="'yellow'">This should not evaluate: {{ 1 +1 }}, but will highlight yellow.
</div>
If you apply
ngNonBindable
to a parent element, Angular disables interpolation and binding of any sort, such as property binding or event binding, for the element's children.
In an Angular template, a binding creates a live connection between a part of the UI created from a template (a DOM element, directive, or component) and the model (the component instance to which the template belongs). This connection can be used to synchronize the view with the model, to notify the model when an event or user action takes place in the view, or both. Angular's Change Detection algorithm is responsible for keeping the view and the model in sync.
Examples of binding include:
text interpolations
property binding
event binding
two-way binding
Bindings always have two parts: a
target
which will receive the bound value, and a
template expression
which produces a value from the model.
Syntax
link
Template expressions are similar to JavaScript expressions.
Many JavaScript expressions are legal template expressions, with the following exceptions.
You can't use JavaScript expressions that have or promote side effects, including:
Assignments (
=
,
+=
,
-=
,
...
)
Operators such as
new
,
typeof
, or
instanceof
Chaining expressions with
;
or
,
The increment and decrement operators
++
and
--
Some of the ES2015+ operators
Other notable differences from JavaScript syntax include:
No support for the bitwise operators such as
|
and
&
New template expression operators, such as
|
Expression context
link
Interpolated expressions have a context—a particular part of the application to which the expression belongs. Typically, this context is the component instance.
In the following snippet, the expression
recommended
and the expression
itemImageUrl2
refer to properties of the
AppComponent
.
Template expressions cannot refer to anything in the global namespace, except
undefined
. They can't refer to
window
or
document
. Additionally, they can't call
console.log()
or
Math.max()
and are restricted to referencing members of the expression context.
Preventing name collisions
link
The context against which an expression evaluates is the union of the template variables, the directive's context object—if it has one—and the component's members.
If you reference a name that belongs to more than one of these namespaces, Angular applies the following precedence logic to determine the context:
The template variable name.
A name in the directive's context.
The component's member names.
To avoid variables shadowing variables in another context, keep variable names unique.
In the following example, the
AppComponent
template greets the
customer
, Padma.
An
ngFor
then lists each
customer
in the
customers
array.
src/app/app.component.ts
@Component({template:`
<div>
<!-- Hello, Padma -->
<h1>Hello, {{customer}}</h1>
<ul>
<!-- Ebony and Chiho in a list-->
<li *ngFor="let customer of customers">{{ customer.value }}</li>
</ul>
</div>
`})classAppComponent{
customers =[{value:'Ebony'},{value:'Chiho'}];
customer ='Padma';}
The
customer
within the
ngFor
is in the context of an
<ng-template>
and so refers to the
customer
in the
customers
array, in this case Ebony and Chiho.
This list does not feature Padma because
customer
outside of the
ngFor
is in a different context.
Conversely,
customer
in the
<h1>
doesn't include Ebony or Chiho because the context for this
customer
is the class and the class value for
customer
is Padma.
Expression best practices
link
When using a template expression, follow these best practices:
Use short expressions
Use property names or method calls whenever possible. Keep application and business logic in the component, where it is accessible to develop and test.
Quick execution
Angular executes a template expression after every change detection cycle. Many asynchronous activities trigger change detection cycles, such as promise resolutions, HTTP results, timer events, key presses, and mouse moves.
An expression should finish quickly to keep the user experience as efficient as possible, especially on slower devices. Consider caching values when their computation requires greater resources.
No visible side effects
link
According to Angular's unidirectional data flow model, a template expression should not change any application state other than the value of the target property. Reading a component value should not change some other displayed value. The view should be stable throughout a single rendering pass.
Idempotent expressions reduce side effects
An idempotent expression is free of side effects and improves Angular's change detection performance. In Angular terms, an idempotent expression always returns
exactly the same thing
until one of its dependent values changes.
Dependent values should not change during a single turn of the event loop. If an idempotent expression returns a string or a number, it returns the same string or number if you call it twice consecutively. If the expression returns an object, including an
array
, it returns the same object
reference
if you call it twice consecutively.
Data binding automatically keeps your page up-to-date based on your application's state.
You use data binding to specify things such as the source of an image, the state of a button, or data for a particular user.
See the
live example
/ download example
for a working example containing the code snippets in this guide.
Data binding and HTML
link
Developers can customize HTML by specifying attributes with string values.
In the following example,
class
,
src
, and
disabled
modify the
<div>
,
<img>
, and
<button>
elements respectively.
<divclass="special">Plain old HTML</div><imgsrc="images/item.png"><buttondisabled>Save</button>
Use data binding to control things like the state of a button:
src/app/app.component.html
<!-- Bind button disabled state to `isUnchanged` property --><buttontype="button" [disabled]="isUnchanged">Save</button>
Notice that the binding is to the
disabled
property of the button's DOM element, not the attribute.
Data binding works with properties of DOM elements, components, and directives, not HTML attributes.
HTML attributes and DOM properties
link
Angular binding distinguishes between HTML attributes and DOM properties.
Attributes initialize DOM properties and you can configure them to modify an element's behavior.
Properties are features of DOM nodes.
A few HTML attributes have 1:1 mapping to properties; for example,
id
Some HTML attributes don't have corresponding properties; for example,
aria-*
Some DOM properties don't have corresponding attributes; for example,
textContent
Remember that HTML attributes and DOM properties are different things, even when they have the same name.
In Angular, the only role of HTML attributes is to initialize element and directive state.
When you write a data binding, you're dealing exclusively with the DOM properties and events of the target object.
Example 1: an
<input>
link
When the browser renders
<input type="text" value="Sarah">
, it creates a corresponding DOM node with a
value
property and initializes that
value
to "Sarah".
<inputtype="text"value="Sarah">
When the user enters
Sally
into the
<input>
, the DOM element
value
property becomes
Sally
.
However, if you look at the HTML attribute
value
using
input.getAttribute('value')
, you can see that the attribute remains unchanged —it returns "Sarah".
The HTML attribute
value
specifies the initial value; the DOM
value
property is the current value.
To see attributes versus DOM properties in a functioning app, see the
live example
/ download example
especially for binding syntax.
Example 2: a disabled button
link
A button's
disabled
property is
false
by default so the button is enabled.
When you add the
disabled
attribute, you are initializing the button's
disabled
property to
true
which disables the button.
<buttondisabled>Test Button</button>
Adding and removing the
disabled
attribute disables and enables the button.
However, the value of the attribute is irrelevant, which is why you cannot enable a button by writing
<button disabled="false">Still Disabled</button>
.
To control the state of the button, set the
disabled
property instead.
Property and attribute comparison
link
Though you could technically set the
[attr.disabled]
attribute binding, the values are different in that the property binding must be a boolean value, while its corresponding attribute binding relies on whether the value is
null
or not.
Consider the following:
The first line, which uses the
disabled
property, uses a boolean value.
The second line, which uses the disabled attribute checks for
null
.
Generally, use property binding over attribute binding as a boolean value is easy to read, the syntax is shorter, and a property is more performant.
To see the
disabled
button example in a functioning application, see the
live example
/ download example
.
This example shows you how to toggle the disabled property from the component.
Types of data binding
link
Angular provides three categories of data binding according to the direction of data flow:
From source to view
From view to source
In a two-way sequence of view to source to view
Type
Syntax
Category
Interpolation
Property
Attribute
Class
Style
{{expression}}[target]="expression"
One-way from data source to view target
Event
(target)="statement"
One-way from view target to data source
Two-way
[(target)]="expression"
Two-way
Binding types other than interpolation have a target name to the left of the equal sign.
The target of a binding is a property or event, which you surround with square bracket (
[ ]
) characters, parenthesis (
( )
) characters, or both (
[( )]
) characters.
The binding punctuation of
[]
,
()
,
[()]
, and the prefix specify the direction of data flow.
Use
[]
to bind from source to view
Use
()
to bind from view to source
Use
[()]
to bind in a two-way sequence of view to source to view
Place the expression or statement to the right of the equal sign within double quote (
""
) characters.
For more information see Interpolation and Template statements.
Binding types and targets
link
The target of a data binding can be a property, an event, or an attribute name.
Every public member of a source directive is automatically available for binding in a template expression or statement.
The following table summarizes the targets for the different binding types.
Type
Target
Examples
Property
Element property
Component property
Directive property
An NgModule describes how the application parts fit together.
Every application has at least one Angular module, the
root
module, which must be present for bootstrapping the application on launch.
By convention and by default, this NgModule is named
AppModule
.
When you use the Angular CLI command
ng new
to generate an app, the default
AppModule
looks like the following:
/* JavaScript imports */import{BrowserModule} from '@angular/platform-browser';import{NgModule} from '@angular/core';import{AppComponent} from './app.component';/* the AppModule class with the @NgModule decorator */@NgModule({
declarations:[AppComponent],
imports:[BrowserModule],
providers:[],
bootstrap:[AppComponent]})exportclassAppModule{}
After the import statements is a class with the
@NgModule
decorator.
The
@NgModule
decorator identifies
AppModule
as an
NgModule
class.
@NgModule
takes a metadata object that tells Angular how to compile and launch the application.
metadata object
Details
declarations
This application's lone component.
imports
Import
BrowserModule
to have browser-specific services such as DOM rendering, sanitization, and location.
providers
The service providers.
bootstrap
The
root
component that Angular creates and inserts into the
index.html
host web page.
The default application created by the Angular CLI only has one component,
AppComponent
, so it is in both the
declarations
and the
bootstrap
arrays.
The
declarations
array
link
The module's
declarations
array tells Angular which components belong to that module.
As you create more components, add them to
declarations
.
You must declare every component in exactly one
NgModule
class.
If you use a component without declaring it, Angular returns an error message.
The
declarations
array only takes declarables. Declarables are components, directives, and pipes.
All of a module's declarables must be in the
declarations
array.
Declarables must belong to exactly one module. The compiler emits an error if you try to declare the same class in more than one module.
These declared classes are visible within the module but invisible to components in a different module, unless they are exported from this module and the other module imports this one.
An example of what goes into a declarations array follows:
A declarable can only belong to one module, so only declare it in one
@NgModule
.
When you need it elsewhere, import the module that contains the declarable you need.
Using directives with
@NgModule
link
Use the
declarations
array for directives.
To use a directive, component, or pipe in a module, you must do a few things:
Export it from the file where you wrote it.
Import it into the appropriate module.
Declare it in the
@NgModule
declarations
array.
Those three steps look like the following. In the file where you create your directive, export it.
The following example, named
ItemDirective
is the default directive structure that the CLI generates in its own file,
item.directive.ts
:
The key point here is that you have to export it, so that you can import it elsewhere.
Next, import it into the
NgModule
, in this example
app.module.ts
, with a JavaScript import statement:
src/app/app.module.ts
import{ItemDirective}from'./item.directive';
And in the same file, add it to the
@NgModule
declarations
array:
src/app/app.module.ts
declarations:[AppComponent,ItemDirective],
Now you could use your
ItemDirective
in a component.
This example uses
AppModule
, but you'd do it the same way for a feature module.
For more about directives, see Attribute Directives and Structural Directives.
You'd also use the same technique for pipes and components.
Remember, components, directives, and pipes belong to one module only.
You only need to declare them once in your application because you share them by importing the necessary modules.
This saves you time and helps keep your application lean.
The
imports
array
link
The module's
imports
array appears exclusively in the
@NgModule
metadata object.
It tells Angular about other NgModules that this particular module needs to function properly.
This list of modules are those that export components, directives, or pipes that component templates in this module reference.
In this case, the component is
AppComponent
, which references components, directives, or pipes in
BrowserModule
,
FormsModule
, or
HttpClientModule
.
A component template can reference another component, directive, or pipe when the referenced class is declared in this module, or the class was imported from another module.
The
providers
array
link
The providers array is where you list the services the application needs.
When you list services here, they are available app-wide.
You can scope them when using feature modules and lazy loading.
For more information, see Providers.
The
bootstrap
array
link
The application launches by bootstrapping the root
AppModule
, which is also referred to as an
entryComponent
.
Among other things, the bootstrapping process creates the component(s) listed in the
bootstrap
array and inserts each one into the browser DOM.
Each bootstrapped component is the base of its own tree of components.
Inserting a bootstrapped component usually triggers a cascade of component creations that fill out that tree.
While you can put more than one component tree on a host web page, most applications have only one component tree and bootstrap a single root component.
This one root component is usually called
AppComponent
and is in the root module's
bootstrap
array.
In a situation where you want to bootstrap a component based on an API response,
or you want to mount the
AppComponent
in a different DOM node that doesn't match the component selector, please refer to
ApplicationRef.bootstrap()
documentation.
More about Angular Modules
link
For more on NgModules you're likely to see frequently in applications, see Frequently Used Modules.
Angular supports most recent browsers.
This includes the following specific versions:
Browser
Supported versions
Chrome
latest
Firefox
latest and extended support release (ESR)
Edge
2 most recent major versions
Safari
2 most recent major versions
iOS
2 most recent major versions
Android
2 most recent major versions
Angular's continuous integration process runs unit tests of the framework on all of these browsers for every pull request, using Sauce Labs.
Polyfills
link
Angular is built on the latest standards of the web platform.
Targeting such a wide range of browsers is challenging because they do not support all features of modern browsers.
You compensate by loading polyfill scripts ("polyfills") for the browsers that you must support.
See instructions on how to include polyfills into your project below.
The suggested polyfills are the ones that run full Angular applications.
You might need additional polyfills to support features not covered by this list.
NOTE
:
Polyfills cannot magically transform an old, slow browser into a modern, fast one.
Enabling polyfills with CLI projects
link
The Angular CLI provides support for polyfills.
If you are not using the CLI to create your projects, see Polyfill instructions for non-CLI users.
The
polyfills
options of the browser and test builder can be a full path for a file (Example:
src/polyfills.ts
) or,
relative to the current workspace or module specifier (Example:
zone.js
).
If you create a TypeScript file, make sure to include it in the
files
property of your
tsconfig
file.
If you are not using the CLI, add your polyfill scripts directly to the host web page (
index.html
).
For example:
src/index.html
<!-- pre-zone polyfills --><scriptsrc="node_modules/core-js/client/shim.min.js"></script><script>/**
* you can configure some zone flags which can disable zone interception for some
* asynchronous activities to improve startup performance - use these options only
* if you know what you are doing as it could result in hard to trace down bugs.
*/// __Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame// __Zone_disable_on_property = true; // disable patch onProperty such as onclick// __zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames/*
* in Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for Edge.
*/// __Zone_enable_cross_context_check = true;</script><!-- zone.js required by Angular --><scriptsrc="node_modules/zone.js/bundles/zone.umd.js"></script><!-- application polyfills -->