Search code examples
angularangular2-directivesangular-directive

what are the normalization rules for properties in Angular 2+?


I ran into a silly issue recently with a component that uses a title property to bind the title of that component. I forgot that title was a known HTML attribute and my users started seeing tooltips with the title over their components.

At first, I just changed the property name to not conflict. But then I remembered that in AngularJS, there are rules about normalization for directives.

I searched (using the search function) the Angular 6+ documentation and I couldn't find the word normalization in there. I also tested and there seems to be some normalization available, at least using data-.

My question is: Is normalization officially supported in Angular 6+? and where can I find documentation for it?

I created a StackBlitz with the following key components to highlight that using data-name="bob" is apparently equivalent to name="bob" :

import { Component, Input } from '@angular/core';

@Component({
  selector: 'hello',
  template: `<h1>Hello {{title}}!</h1>`,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
  @Input() title: string;
}
<hello data-title="bob"></hello>
<hello title="bob"></hello>

Solution

  • If you are using a directive that has an input that could be in conflict with an attribute for the parent element you have 3 options.

    1. Change the directive's input to a non-conflicting name.
    2. Use binding notation

      <button title="PushMe" titleTesting [title]="'dont push me'">Push this</button>
      
    3. Use attribute notation.

      <button [attr.title]="'PushMe'" titleTesting title="dont push me">Push this</button>
      

    Directive code used in above template:

    @Directive({
      selector: '[titleTesting]'
    })
    export class TitleTestDirective implements OnInit {
      @Input() title: string;
      ngOnInit(){
        console.log(this.title);
      }
    }
    

    Finally if the values should be the same and is a constant defined in the template then proceed as normal as both the element and your directive would get the same value, example:

    <button titleTesting title="dont push me">Push this</button>
    

    See also Binding syntax: An overview and Property binding or interpolation?, attribute binding, and a stackblitz.


    Normalization

    In short angular does not support or do anything with normalization. You had directive listed but had a component example, a component would not have any conflicting attributes/inputs which is why I chose to model an example using directives.

    data- is an HTML5 construct. angular does not do anything with that directly. If you do include data- though it will still bind as expected to the Input but it won't be set on any html specific attribute. Example: data-title="some title". Based on the data- documentation this is expected behavior.

    You can supply both a data- and a non data- element of the same type for different values but the order in which they appear is important. Example:

    <button titleTesting title="Push me" data-title="DOn't push me">Push this</button>