X Tutup
Skip to content

Have a schema for bindings, and report error on miss-typed bindings. #2014

@mhevery

Description

@mhevery

Quick, can you spot an error? (Currently it fails silently.)

<ul>
  <li *ng-for="item in items">{{item}}</li>
</ul>

There are two issues:

  • It is for of not for in
  • It needs var item or #item instead of item

The current binding expands to

<ul>
  <template [ng-for]="item" [ng-for-in]="items">
    <li>{{item}}</li>
  </template>
</ul>

but it should have been:

<ul>
  <template ng-for #item [ng-for-of]="items">
    <li>{{item}}</li>
  </template>
</ul>
  • it fails to match [ng-for][ng-for-of] and turns the binding to element property bindings (ie monkey patches the properties on template element) (This should have failed because it should have noticed that the element does not have ngFor or ngForOf and hence should have prevent the monkey patch)
  • it then fails to notice that item is not defined (because we are trying to define it) (This should have failed!)

GOAL

  • Identify typos in the HTML bindings and throw errors to hint to developers.

Strategy

The way to do this properly is to have a schema for which properties are allowed on which DOM elements. Currently we can lazy compute such as schema for DOM elements. But we can not compute them for WebComponents. So the proposal is to WebComponents publish their own schema.

<div [title]="exp"></div>
<svg>
  <g [x]="exp">
<svg>

We can lazy compute that title is a property of div (by noticing that title is a property of the div element). This can be done in Compiler during the compilation step. The result would be something like:

var schema = {
  'div': { 'title': 'title' },
  'svg:g': { 'x': '@x' }
}

The above would tell us that it is OK to bind to title to internal property name title on a div. (We need this as some properties don't properly rename see { 'inner-html': 'innerHTML', 'readonly': 'readOnly', 'tabindex': 'tabIndex'} )

We could also tell that g is instance of SVGElement and in that case we bind to the x attribute rather then the default x properties.

But this does not work with WebComponents because during the compilation the element is in template tag and is not active, as a result we can not query its properties.

<google-youtube [video-id]="exp">

there is no way for Angular to know if videoId is a valid, as a result we need to configure this:

@View({
  webComponents: {
    'google-youtube': {'!extends': 'div', 'video-id': 'videoId'}
  }
})

NOTE: !extends is used to say that all mappings from the div should be included.

By adding this schema definition Angular will be able to correctly resolve web-component assignments.

Resolution Rules

<div [foo]="exp" bar="literal">
  1. foo (property binding)
    • Is in schema => then assign foo property to element
    • is in schema and is a directive => assign to foo property and to the directive
    • is not in schema but it has a directive => assign to directive only
    • is not in schema and does not have a directive => Throw an error
  2. bar (just a literal)
    • Is in schema => no-op (we leave the property as is)
    • is in schema and is a directive => assign the literal one-time to the directive
    • is not in schema but it has a directive => assign the literal one-time to the directive
    • is not in schema and does not have a directive => Throw an error. (Implication is that if a component wants to use attributes for CSS which are not part of DOM, they will have to be declared ahead of time in the schema.)

Error handling.

With the above rules the example will produce these errors:

<ul>
  <li *ng-for="item in items">{{item}}</li>
</ul>
<ul>
  <template [ng-for]="item" [ng-for-in]="items">
    <li>{{item}}</li>
  </template>
</ul>
  • Can not bind 'item' to 'ng-for' because 'ng-for' is not a property of [TemplateElement, NgFor].
  • Can not binditemsto 'ng-for-in' because 'ng-for' is not property of [TemplateElement, NgFor].

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    X Tutup