How to use extrapolation of Angular 2 in html element attributes?

I want to bind some data to non-standard attributes of an html element. However, the {{}} attributes are not extrapolated. I looked at other related posts since " Angularjs templateUrl cannot bind attributes inside ng-repeat ", which is an angular 1 solution for custom directives.

For example, I have:

size = 500; 

I want the following SVG element to work correctly:

 <svg xmlns="http://www.w3.org/2000/svg/" width="{{size}}" height="{{size}}"> <rect width="{{size}}" height="{{size}}" fill="#DCB35C"/> </svg> 

How to do this in angular 2?

+6
source share
3 answers

Short answer

If there is no 1: 1 mapping between the HTML attribute and the DOM property, you must use the attribute binding syntax otherwise Angular 2 will report a "Template parsing error" error.

Examples:

  • [attr.my-custom-attribute]="myComponentValue"
  • [attr.colspan]="1 + 1"

In your case, the SVG element has DOM properties of width and height, but they are not what you expect. They are SVGAnimatedLength objects. Trying to establish its value, the old way will do nothing. Therefore, your template does not work as you expect and does not report an error. Switching to attribute binding syntax will fix this behavior: [attr.width]="width" [attr.height]="height"

Detailed description

There is a big conceptual difference between how attribute bindings work in Angular 1 and Angular 2.

In Angular 1, setting a custom attribute looks like this:

  • <div a-custom-attribute="I am a custom {{ 'attribute' }}">Text Content</div>
  • <div ng-attr-a-custom-attribute="I am a custom {{ 'attribute' }}">Text Content</div> - this syntax allows you to bind to attributes that would otherwise be processed by browsers (for example , circle of SVG elements [cx], src attribute for IMG element, etc.)

There is another story in Angular 2:

Angular 2 introduced, as they put it, a new mental model : instead of binding to HTML attributes, which it binds to DOM properties . Understanding the difference between an HTML attribute and a DOM property is critical to understanding how Angular 2 binding works.

A binding to a DOM property might look like this:

  • <img [src]="heroImageUrl">
  • <img bind-src="heroImageUrl">
  • <img src="{{ heroImageUrl }}"> - this may seem a bit confusing, especially if someone has an AngularJS 1 background, but Angular 2 translates these interpolations into the corresponding property bindings before rendering the view ( source ). It is important to keep in mind that like Mark , indicated in the comments section, after the interpolation has been carried out, its result is then converted to a string ( source ). This means that this syntax is limited only by the assignment of string values.

Note that if the name does not match the DOM property, Angular 2 reports an โ€œunknown native propertyโ€ error:

 // Template parse errors: // Can't bind to 'colspan' since it isn't a known native property <tr><td colspan="{{1 + 1}}">Three-Four</td></tr> // Template parse errors: // Can't bind to 'madeUpProperty' since it isn't a known native property <div [madeUpProperty]="My custom {{ 'madeUpProperty' }}"></div> 

This means that binding to a DOM object does not require the use of attribute binding syntax .

Finally, I believe that as a good rule, you should always use property binding syntax (for example [src]="heroImageUrl" ) in favor of interpolation (for example src="{{heroImageUrl}}" when he wants to change the property of the DOM element , since the latter is limited only to the transmitted string values. Another reason is that if someone has an AngularJS 1 background, this should reduce the confusion between setting the attribute and the DOM property.

+12
source

You must bind width and height using attribute binding, having the attr prefix before the binding, for example [attr.*] .

Markup

 <svg xmlns="http://www.w3.org/2000/svg/" [attr.width]="size" [attr.height]="size"> <rect [attr.width]="width" [attr.height]="height" fill="#DCB35C" /> </svg> 

Class

 import {Component} from 'angular2/core'; import {bootstrap} from 'angular2/platform/browser'; @Component({ selector: 'demo-app', templateUrl: 'src/app.html', pipes: [] }) export class App { width: number = 100; height: number=100; size: number=100; constructor() { } } bootstrap(App); 

Demo plunkr


As requested to add a size value using some constant string value, you just need to put this on attribute , like [attr.width]="size + '5'"

 <svg xmlns="http://www.w3.org/2000/svg/" [attr.width]="size" [attr.height]="size"> <rect [attr.width]="width + '5'" [attr.height]="height + '5'" fill="#DCB35C" /> </svg> 

Updated Plunkr

+4
source
 <svg xmlns="http://www.w3.org/2000/svg/" [attr.width.px]="size" [attr.height.px]="size"> <rect [attr.width.px]="width" [attr.height.px]="height" fill="#DCB35C" /> </svg> 
+4
source

All Articles