6.0 KiB
Angular2 templates are now case-sensitive and use camelCase in many places where dash-case was previously used ([design doc] (https://docs.google.com/document/d/1UMxTIUBTIUZNfOqwMhkLg0ANFSBtLIK9JsIu77EZaBA/edit?ts=564f7dd4)).
Overview
Where you used to write:
<my-cmp (some-event)="someAction()" [some-property]="expression" #some-var>
in order to:
- bind to the
someEvent
event, - bind to the
someProperty
property, - create a
someVar
local variable
You should now write:
<my-cmp (someEvent)="someAction()" [someProperty]="expression" #someVar>
Notes:
- while tag name are case sensitive, the best practice is to use dash case for component elements so that the browser interpret them as custom elements,
(some-event)
would now bind to thesome-event
event (i.e. there is no implicit dash to camel case conversion),(some-property)
would now bind to thesome-property
property (i.e. there is no implicit dash to camel case conversion),#some-var
is not allowed any more ("-" can not be used in variable names).
Migration
Templates
- Directives selectors, property bindings, event bindings, template variables and template element attributes should be changed to camel case:
Examples:
<p *ng-if="cond">
should be changed to<p *ngIf="cond">
,<my-cmp [my-prop]="exp">
should be changed to<my-cmp [myProp]="exp">
,<my-cmp (my-event)="action()">
should be changed to<my-cmp (myEvent)="action()">
,<my-cmp [(my-prop)]="prop">
should be changed to<my-cmp [(myProp)]="prop">
,<input #my-input>
should be changed to<input #myInput>
,<template ng-for #my-item [ng-for-of]=items #my-index="index">
should be changed to<template ngFor #my-item [ngForOf]=items #myIndex="index">
,
Note: while the tag names are now case-sensitive the best practice is to keep them lower-dash-cased so that the browser
treat them as custom elements. Using dashes in custom element names is required by the Custom Element HTML Spec.
This explains why the <router-outlet>
component is left unchanged.
on-
, bindon-
, bind-
and var-
prefixes are still part of the canonical syntax and should remain unchanged (lower cased):
on-some-event
should be changed toon-someEvent
,bind-my-prop
should be changed tobind-myProp
,bindon-my-prop
should be changed tobindon-myProp
,var-my-var
should be changed tovar-myVar
.
- Update variable binding
<p #var1="a-b" var-var2="c-d">
should be changed to<p #var1="aB" var-var2="cD">
- The
template
attribute values should also be updated in the same way
<p template="ng-for #my-item of items #my-index = index">
should be changed to <p template="ngFor #myItem of items #myIndex = index">
.
Note that both angular directives and your own directives must be updated in the same way.
Directives and Components
Take the following steps to upgrade your directives and components:
- Update the selector:
@Directive({selector: 'tag[attr][name=value]'})
@Component({selector: 'tag[attr][name=value]'})
Tag and attributes names are case sensitive:
- For tag names, the best practice is to keep them lower dash cased, do not update them,
- For attribute names, the best practice is to convert them from lower dash case to camel case.
Examples:
custom-tag
should staycustom-tag
(do not update tag names),[attr-name]
should be updated to[attrName]
,[attr-name=someValue]
should be updated to[attrName=someValue]
,custom-tag[attr-name=someValue]
should be updated tocustom-tag[attrName=someValue]
Note: attribute values and classes are still matched case insensitive.
- Update the inputs
@Directive({inputs: ['myProp', 'myOtherProp: my-attr-name']})
As attribute names are now case sensitive, they should be converted from dash to camel case where they are specified. The previous decorator becomes:
@Directive({inputs: ['myProp', 'myOtherProp: myAttrName']})
Notes:
- only the long syntax (with ":") needs not be updated,
- properties
is the legacy name for inputs
and should be updated in the same way - it is a good idea to replace
properties
with inputs
at the same time as support for the former will be removed soon.
The same applies for the @Input
decorator:
@Input() myProp;
@Input('my-attr-name') myProp;
That is they only need to be updated when the attribute name is specified:
@Input() myProp; // Nothing to update
@Input('myAttrName') myProp; // Convert the attribute name to camel case
- Update the outputs
Update the outputs in the same way the inputs are updated:
@Directive({outputs: ['myEvent', 'myOtherEvent: my-event-name']})
should be updated to:
@Directive({outputs: ['myEvent', 'myOtherEvent: myEventName']})
If you use events
instead of outputs
you should update in the same way and switch to outputs
as events
is deprecated.
@Output() myEvent;
@Output('my-event-name') myEvent;
should be changed to:
@Output() myEvent;
@Output('myEventName') myEvent;
- Update the host bindings
@Directive({
host: {
'[some-prop]': 'exp',
'[style.background-color]': 'exp',
'[class.some-class]': 'exp',
'(some-event)': 'action()',
'some-attr': 'value'
}
})
should be changed to:
@Directive({
host: {
'[someProp]': 'exp',
'[style.background-color]': 'exp',
'[class.some-class]': 'exp',
'(someEvent)': 'action()',
'some-attr': 'value'
}
})
The property bindings ([...]
) and event bindings ((...)
) must be updated in the same way as they are updated in a
template (reminder: [attr.]
, [class.]
and [style.]
should not be converted to camel case).
- Update export name
@Directive({
exportAs: 'some-name'
})
should be changed to:
@Directive({
exportAs: 'someName'
})