Angular Data Binding

technologytutorialangular
by

Dimitar Stoev

Every component has a template. The ability to communicate between the information in the component and the view is called data binding.

The syntax is HTML with some additional Angular features like loops, conditions and event bindings.

Angular has three main categories of data binding divided in from the component to the view, the way back and two directional.

We can further extract it to this:

  • Interpolation
  • Property binding
  • Attribute, class, style
  • Event binding
  • Two way binding
  • Host binding
  • Data bindings are dynamic!

    In the template to bind data we can use the Template syntax. The template Angular uses to display the view is valid HTML, but with added functionalities.

    Template syntax ( or expressions ) are limited JavaScript functions that:

  • Must produce a value
  • A property name
  • A method call
  • It has its own expression context and therefore it can't access the global namespace.

    Since Angular stores the current value and each time change detection runs, it checks the value with the changed data.

    If the expression doesn't generate a value, it can't be changed. That's why Template expressions must always return a value. Angular executes the expression and assigns it to a property of a target.

    You are allowed to use two special operators:

  • Pipes
  • Optional chaining operator: : ?
  • Template expressions cannot refer to anything in the global namespace, ( except undefined ). They can't refer to window or document. That is the reason we can't call console.log().

    You are restricted using the following in the JavaScript expressions:

  • No new operator, typeof or instanceof
  • No assignment, increment, decrement operators
  • Only one expression. It is not allowed to chain with ';', 'or', ','
  • Can't access global namespace
  • The non null assertion operator !
  • It's important to point out the following

    Template expressions are evaluated every time a change detection cycle is executed.

    Because of that, they have to be simple logic and have a fast execution rate.

    Template expressions have to be idempotent ( simply: No visible side effects ).

    If a template expression returns a primitive type ( string, number, boolean ) , it should return the same value when called twice in a row.

    if a template expression returns an object ( this could be an Array or Date, etc. ) it should return the same object reference ( reference value )

    For security reasons, Angular does not support the <script></script> tag.

    Template statements are part of the event binding communication between the HTML ( the view ) and the Angular component ( the TypeScript logic ).

    Binding is only checked once in production mode!

    It is important to point out here the unidirectional data flow in Angular. The component tree is always checked for changes from parent to child.

    Interpolation

    Changes to title's value are automatically propagated to the DOM ( textContent property ) by Angular change detection.

    Interpolation is a one way data binding expression toString() to textContent DOM property.

    Interpolation always converts the data to a string.

    It binds a template expression to textContent DOM property.

    The textContent property accepts only strings ( texts )

    Interpolation can also be used as property interpolation.


    Property binding

    Property data binding is one way data binding.

    Parent expression to child component's Input property.


    The @Input() is a special Angular decorator that allows us to pass data between parent and a child component. The value is updated every time Angular detects a change in the parent component.

    We can also use an alias to connect the HTML target property and use it as simply title property in the .ts component logic.

    Input properties are a great way to make components more reusable.


    The target name is always the name of a property. The current target property is in valid square brackets and the componentTitle is the parent template expression.

    Element properties may be the more common targets, but Angular looks first to see if the name is a property of a known directive!

    While the interpolation is evaluated and always converted to string, the property binding expression is evaluated and the result is assigned to the DOM or component property without the need to convert it to string.

    The binding is not limited only to parent properties, but also includes any valid template expression!

    Attributes, Class and Style binding

    Attribute binding is similar to property binding, but with a specific syntax. The brackets are still there, but there is a prefix attr. and the name of the attribute.

    We can use the attribute interpolation to assign data to HTML elements.


    The attribute name has to be valid

    Class attributes are useful in certain situations. One such situation could be conditional styling.


    The above example works with Truthy expressions.

    It could also be a function call. A perfect way to toggle a single class name, but for multiple names it is better to do class binding with [ngClass] - A built- in Angular directive.

    It is a perfect way to control CSS classes dynamically.


    Even better way to do it is:


    Style binding is similar to [ngClass]. It is also an attribute directive built in in Angular.


  • NgClass modifies an HTML element by adding or removing a class
  • NgStyle controls a single style property value for an element
  • Event binding

    Events are a powerful way to bind data and information. It lets us listen for user interaction. The data in this situation flows from the child component to the parent one.


    The brackets again are valid HTML. Every time an event is fired, the method update_data is called.

    The update_data is a template statement.

    As a difference to our previous examples, this one is binding from the DOM event to the Component. As a result, we are not writing any template expressions. This method could be void and we may not return any value. Template statements have side effects and are not following the Idempotence rule.

    These methods are executed only when an event is fired, and not every time change detection runs.

    Every time an event is fired and executed, Angular runs a change detection!

    Any valid event is a valid Angular event.


    If we console.log the $event that is passed with the event we can see all the information that is passed with the Event. That is a lot of information that we may not be interested in. In order to handle this issue we have the template variable.


    Angular checks if the name of the event matches an event property of a known directive. If it doesn't it binds to the event of the underlying DOM element. If that fails too, it throws an error "unknown directive".

    Unlike Template expressions, template statements and methods can support assignment and can be chained.

    Template statements don't have to do anything when an event is fired and this could be used as a way to trigger change detection.

    Another way of binding is the custom events.

    If we want the child to send information to the parent, Angular provide us with the:

    @Output()


    The child component uses the @Output() property to raise an event to notify the parent of the change. To raise an event, an @Output() must have the type of EventEmitter, which is a class in @angular/core that you use to emit custom events.


    This alone won't do anything, until we actually send the data.


    To be used, we have to handle the event in the parent component.


    The $event contains the value we are sending with the emit method.

    We can use the @Output() and the @Input() together.

    Two way data binding

    There is a built- in directive in Angular for two way data binding. A syntactic sugar for a property binding and an event binding.


    It could be used only with primitive types of data. The direction is from the Component to the Form Element/DOM and back.

    Changes to the name property are automatically propagated to the DOM ( value property ) by Angular change detection.

    Changes to the input's value are automatically propagated to the component property and that triggers change detection.

    The [(ngModel)] could be said as an Input and Output, but shorthand for it. What is happening under the hood is this

    When used on input, NgModel binds to the DOM property value.


    Keep in mind you may receive an error with the following: $event.target.value. Property ‘value’ does not exist on type ‘EventTarget’ - you may see a solution in the demo project bellow in the two-way-binding.component

    In the (ngModelChange) event, the $event is not a DOM event object, but the emitted value of the input. This is what the ngModel directive emits.

    In order to get access to the whole $event object, use (change)="onChange($event)"

    This two way data binding could be used also between components.

    The structure is the same, but it is important to point out that the output event has to be fired by emit().

    We don't need to call the emit() when we change the input property in the child when the property is a reference type.

    That is because the parent will automatically "see" this change.

    One difference is that with two way binding between components we can bind reference type and not only primitives.

    Since change detection runs from top to bottom, we have to emit the child changes to the parent. Changes from parent to child are automated, because when Angular detects a change in the parent component, it updates the value and this forces an update on the child component.

    Messing the unidirectional data flow could lead to pretty common mistake and error:

    ExpressionChangedAfterItHasBeenCheckedError


    When using two-way data binding between components, output property must be named a certain way. If the input property name is name, what must the output property be named nameChange

    Host binding

    Host binding is a little bit unexplained and usually people don't mention it.

    Angular automatically checks host property bindings during change detection, and if a binding changes it updates the host element of the directive.


    With the code above we can bind to an element and set the attribute with a value of "true".

    We can bind any kind of attribute to the host.

    In order to update the state back we have to set a listener.


    Demo

    Every example could be seen here:

    https://github.com/dimitar-stoev/angular-data-binding/

    https://stackblitz.com/edit/angular-ivy-sn81eh?file=README.md

    https://angular-ivy-sn81eh.stackblitz.io/


    More from this category