Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Request full support for the Web Components Custom Elements spec in version 1.7 #16428

Closed
1 of 3 tasks
raviolibhat opened this issue Jan 30, 2018 · 9 comments
Closed
1 of 3 tasks

Comments

@raviolibhat
Copy link

I'm submitting a ...

  • bug report
  • feature request
  • other

Current behavior:
Web Components aim to be a standards based web framework for browsers very soon. The Custom Elements spec within it is crucial. From Custom Elements Everywhere one can see that AngularJS 1.6 passes all basic tests but none of the advanced tests. This feature request is to provide full support in version 1.7 and pass the advanced tests as well.

Expected / new behavior:
Long term support for 1.7 has been announced to extend for three years. Hence a goal in this request is to make the transition from AngularJS 1.7 to Web Components directly possible, instead of an intermediate step to another framework.

Minimal reproduction of the problem with instructions:

AngularJS version: 1.7.0

Browser: [all]

Anything else:

@Narretz
Copy link
Contributor

Narretz commented Jan 31, 2018

This would be quite a complex task at this point, because AngularJS misses the possibility to bind to arbitrary attributes / listen to arbitrary events, see https://custom-elements-everywhere.com/

I think @gkalpak knows more about this.

@gkalpak
Copy link
Member

gkalpak commented Jan 31, 2018

It is definitely an interesting feature to consider. I don't think it would be too complicated (I expect most complications to arise around sanitization - if we choose to have it 😉).

It is worth investigating more imo.

BTW, you can implement two basic (somewhat hacky) directives to handle the missing features for you (with somewhat awkward syntax). Basically, you need a way to declaratively bind to arbitrary properties:

// Usage:
// ```html
// <!-- Bind `$ctrl.bar` to the `foo` property of `<my-element>`. -->
// <my-element ng-prop="foo->$ctrl.bar">
//
// <!-- Bind multiple to properties. -->
// <my-element ng-prop="foo->$ctrl.bar|||baz->$ctrl.qux+'xyz'">
// ```
.directive('ngProp', function ngPropDirective() {
  // Post-link
  return (scope, elem, attrs) => {
    attrs.ngProp.
      split('|||').
      map(x => /^(.+?)->(.+)$/.exec(x).slice(1)).
      forEach(([propName, exp]) => {
        const watchListener = newValue => elem[0][propName] = newValue;
        scope.$watch(exp, watchListener);
      });
  };
}

Then, you also need a way to declaratively listen to arbitrary events:

// Usage:
// ```html
// <!-- Listen to `foo` event and call `$ctrl.onFoo()`. -->
// <my-element ng-on="foo->$ctrl.bar()">
//
// <!-- Pass the event object to the listener. -->
// <my-element ng-on="foo->$ctrl.bar($event)">
//
// <!-- Listen to multiple events. -->
// <my-element ng-on="foo->$ctrl.bar()|||baz->$ctrl.qux = $ctrl.qux + 1">
// ```
.directive('ngOn', function ngOnDirective($parse) {
  // Post-link
  return (scope, elem, attrs) => {
    attrs.ngOn.
      split('|||').
      map(x => /^(.+?)->(.+)$/.exec(x).slice(1)).
      forEach(([eventName, exp]) => {
        const parsedExp = $parse(exp);
        const listener = $event => scope.$apply(() => parsedExp(scope, {$event}));
        elem.on(eventName, listener);
      });
  };
}

Here is a demo.

@mattdsteele
Copy link

For reference, the other library I've used to do arbitrary prop bindings: https://github.com/robdodson/angular-custom-elements

@gkalpak gkalpak modified the milestones: Ice Box, 1.7.x, 1.6.x Feb 1, 2018
@peterblazejewicz
Copy link

peterblazejewicz commented Feb 18, 2018

Hi folks,
I think, if it is added in 1.7 it will help to migrate core features of existing apps into platform/library agnostic, standard compliant solution. I could imagine of porting part of UI into custom elements and later use them in any other application.
Thanks!

@Narretz Narretz modified the milestones: 1.6.x, 1.7.x Apr 12, 2018
@gkalpak gkalpak self-assigned this May 9, 2018
@Narretz Narretz self-assigned this May 23, 2018
@Narretz
Copy link
Contributor

Narretz commented May 23, 2018

Notes:

  • we can add this to the compiler - the cost shouldn't be too high, but we could always put this feature behind a flag
  • Angular sets a security context to specifc properties like innerHTML and sanitizes the input (something with a schemer)

@benoitjchevalier
Copy link

Is there any chance this will make it onto LTS?

@gkalpak
Copy link
Member

gkalpak commented May 24, 2018

We would very much like it to make it. But given there is only one month left for feature development, we can't make any promises.
If anyone from the community wants to take a stub at it, that would be 👌

@gkalpak
Copy link
Member

gkalpak commented May 30, 2018

BTW, this is the schema used by Angular to assign security contexts to different elements: dom_security_schema.ts

@gkalpak
Copy link
Member

gkalpak commented Jun 1, 2018

BTW2, if we implement this (i.e. ng-bind and ng-on), then it would fairly straightforward to also implement ng-bindon (#15464) 😁

*: Names are debateable 😛

@jbedard jbedard self-assigned this Jun 11, 2018
jbedard added a commit to jbedard/angular.js that referenced this issue Jun 26, 2018
Narretz pushed a commit to Narretz/angular.js that referenced this issue Jul 12, 2018
jbedard added a commit to jbedard/angular.js that referenced this issue Jul 25, 2018
jbedard added a commit to jbedard/angular.js that referenced this issue Jul 30, 2018
…ings

Properties:

Previously only arbitrary DOM attribute bindings were supported via interpolation such as `my-attribute="{{expression}}"` or `ng-attr-my-attribute="{{expression}}"`, and only a set of distinct properties could be bound. `ng-prop-*` adds support for binding expressions to any DOM properties. For example `ng-prop-foo=”x”` will assign the value of the expression `x` to the `foo` property, and re-assign whenever the expression `x` changes.

Events:

Previously only a distinct set of DOM events could be bound using such as `ng-click`, `ng-blur` etc. `ng-on-*` adds support for binding expressions to any DOM event. For example `ng-on-bar=”barOccured($event)”` will add a listener to the “bar” event and invoke the `barOccured($event)` expression.

For properties or events using mixed case underscores can be used before capital letters. For example `ng-prop-my_prop="x"` will bind `x` to the `myProp` property, and `ng-on-my_custom_event="x()"` will invoke `x()` on the `myCustomEvent` event.

Fixes angular#16428
Fixes angular#16235
Closes angular#16614
jbedard added a commit to jbedard/angular.js that referenced this issue Jul 30, 2018
…ings

Properties:

Previously only arbitrary DOM attribute bindings were supported via interpolation such as
`my-attribute="{{expression}}"` or `ng-attr-my-attribute="{{expression}}"`, and only a set of
distinct properties could be bound. `ng-prop-*` adds support for binding expressions to any DOM
properties. For example `ng-prop-foo=”x”` will assign the value of the expression `x` to the
`foo` property, and re-assign whenever the expression `x` changes.

Events:

Previously only a distinct set of DOM events could be bound using such as `ng-click`, `ng-blur` etc.
`ng-on-*` adds support for binding expressions to any DOM event. For example
`ng-on-bar=”barOccured($event)”` will add a listener to the “bar” event and invoke the
`barOccured($event)` expression.

For properties or events using mixed case underscores can be used before capital letters. For
example `ng-prop-my_prop="x"` will bind `x` to the `myProp` property, and
`ng-on-my_custom_event="x()"` will invoke `x()` on the `myCustomEvent` event.

Fixes angular#16428
Fixes angular#16235
Closes angular#16614
jbedard added a commit to jbedard/angular.js that referenced this issue Jul 30, 2018
…ings

Properties:

Previously only arbitrary DOM attribute bindings were supported via interpolation such as
`my-attribute="{{expression}}"` or `ng-attr-my-attribute="{{expression}}"`, and only a set of
distinct properties could be bound. `ng-prop-*` adds support for binding expressions to any DOM
properties. For example `ng-prop-foo=”x”` will assign the value of the expression `x` to the
`foo` property, and re-assign whenever the expression `x` changes.

Events:

Previously only a distinct set of DOM events could be bound such as `ng-click`, `ng-blur` etc.
`ng-on-*` adds support for binding expressions to any DOM event. For example
`ng-on-bar=”barOccured($event)”` will add a listener to the “bar” event and invoke the
`barOccured($event)` expression.

For properties or events using mixed case, underscores can be used before capital letters. For
example `ng-prop-my_prop="x"` will bind `x` to the `myProp` property, and
`ng-on-my_custom_event="x()"` will invoke `x()` on the `myCustomEvent` event.

Fixes angular#16428
Fixes angular#16235
Closes angular#16614
jbedard added a commit to jbedard/angular.js that referenced this issue Jul 30, 2018
…ings

Properties:

Previously only arbitrary DOM attribute bindings were supported via interpolation such as
`my-attribute="{{expression}}"` or `ng-attr-my-attribute="{{expression}}"`, and only a set of
distinct properties could be bound. `ng-prop-*` adds support for binding expressions to any DOM
properties. For example `ng-prop-foo=”x”` will assign the value of the expression `x` to the
`foo` property, and re-assign whenever the expression `x` changes.

Events:

Previously only a distinct set of DOM events could be bound using directives such as `ng-click`,
`ng-blur` etc. `ng-on-*` adds support for binding expressions to any DOM event. For example
`ng-on-bar=”barOccured($event)”` will add a listener to the “bar” event and invoke the
`barOccured($event)` expression.

For properties or events using mixed case, underscores can be used before capital letters. For
example `ng-prop-my_prop="x"` will bind `x` to the `myProp` property, and
`ng-on-my_custom_event="x()"` will invoke `x()` on the `myCustomEvent` event.

Fixes angular#16428
Fixes angular#16235
Closes angular#16614
jbedard added a commit to jbedard/angular.js that referenced this issue Jul 31, 2018
…ings

Properties:

Previously only arbitrary DOM attribute bindings were supported via interpolation such as
`my-attribute="{{expression}}"` or `ng-attr-my-attribute="{{expression}}"`, and only a set of
distinct properties could be bound. `ng-prop-*` adds support for binding expressions to any DOM
properties. For example `ng-prop-foo="x"` will assign the value of the expression `x` to the
`foo` property, and re-assign whenever the expression `x` changes.

Events:

Previously only a distinct set of DOM events could be bound using directives such as `ng-click`,
`ng-blur` etc. `ng-on-*` adds support for binding expressions to any DOM event. For example
`ng-on-bar="barOccured($event)"` will add a listener to the “bar" event and invoke the
`barOccured($event)` expression.

Since HTML attributes are case-insensitive, property and event names are specified in snake_case
for `ng-prop-*` and `ng-on-*`. For example, to bind property `fooBar` use `ng-prop-foo_bar`, to
listen to event `fooBar` use `ng-on-foo_bar`.

Fixes angular#16428
Fixes angular#16235
Closes angular#16614
jbedard added a commit to jbedard/angular.js that referenced this issue Jul 31, 2018
…ings

Properties:

Previously only arbitrary DOM attribute bindings were supported via interpolation such as
`my-attribute="{{expression}}"` or `ng-attr-my-attribute="{{expression}}"`, and only a set of
distinct properties could be bound. `ng-prop-*` adds support for binding expressions to any DOM
properties. For example `ng-prop-foo="x"` will assign the value of the expression `x` to the
`foo` property, and re-assign whenever the expression `x` changes.

Events:

Previously only a distinct set of DOM events could be bound using directives such as `ng-click`,
`ng-blur` etc. `ng-on-*` adds support for binding expressions to any DOM event. For example
`ng-on-bar="barOccured($event)"` will add a listener to the "bar" event and invoke the
`barOccured($event)` expression.

Since HTML attributes are case-insensitive, property and event names are specified in snake_case
for `ng-prop-*` and `ng-on-*`. For example, to bind property `fooBar` use `ng-prop-foo_bar`, to
listen to event `fooBar` use `ng-on-foo_bar`.

Fixes angular#16428
Fixes angular#16235
Closes angular#16614
@jbedard jbedard closed this as completed in dedb10c Aug 2, 2018
Narretz pushed a commit that referenced this issue Aug 3, 2018
…ings

Properties:

Previously only arbitrary DOM attribute bindings were supported via interpolation such as
`my-attribute="{{expression}}"` or `ng-attr-my-attribute="{{expression}}"`, and only a set of
distinct properties could be bound. `ng-prop-*` adds support for binding expressions to any DOM
properties. For example `ng-prop-foo="x"` will assign the value of the expression `x` to the
`foo` property, and re-assign whenever the expression `x` changes.

Events:

Previously only a distinct set of DOM events could be bound using directives such as `ng-click`,
`ng-blur` etc. `ng-on-*` adds support for binding expressions to any DOM event. For example
`ng-on-bar="barOccured($event)"` will add a listener to the "bar" event and invoke the
`barOccured($event)` expression.

Since HTML attributes are case-insensitive, property and event names are specified in snake_case
for `ng-prop-*` and `ng-on-*`. For example, to bind property `fooBar` use `ng-prop-foo_bar`, to
listen to event `fooBar` use `ng-on-foo_bar`.

Fixes #16428
Fixes #16235
Closes #16614
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants