New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: <proposal #someId [bind]="expr" (event)="doWork()"> #133

Closed
mhevery opened this Issue Oct 31, 2014 · 351 comments

Comments

Projects
None yet
@mhevery
Member

mhevery commented Oct 31, 2014

Update from @IgorMinar on 2014-11-10:

To summarize the constraints, the solution we are looking for must match the following:

  1. Be valid HTML (see this issue for discussion about [, ], (, ) chars in attr name of valid html).
  2. Be Web designer friendly
  3. Interoperable with web-components (don't interfere with web component initialization)
  4. Support debugging story via inspecting rendered DOM during development
  5. The syntax must clearly distinguish between 1) string literal; 2) expression (binding); 3) expression (events) 4) declaration of variables. All of this must be clear from template without understanding which directives are active or what the internal semantics of these directives are.
  6. Support additional info or options for each binding in order to avoid directive specific micro-syntaxes (this enables for tooling to work without hardcoding support for micro-syntaxes). This must be supported in a way that preserves constraint no. 5.

Please don't propose any new solutions that don't meet all of the criteria above.


Original description:

Current proposal for Angular2 syntax is

<element #someId [bind]="expr" (event)="doWork()">

There are several issues with this proposal which have come to light recently. These are:

element.setAttribute('[foo]', 'exp') does not work.

In all browsers tested (Chrome, IE, Safari) the above is an error. This means that it is not possible to create a valid template programatically. It is still possible to parse and read the template.

It seems like that calling setAttribute requires first character to be a-z|_ specifically - is not allowed as starting character nor are any of these ~!@#$%^&*(){}.

Third part HTML shorteners don't support non-standard characters.

Tools such as Slim, Haml, JADE don't support generating special characters. This would break the backend servers such as Ruby on Rails.

SVG requires valid XML and []()# is not valid XML.

This seems to be in the spec, but at least Chrome browser does not have issues with these characters. Need to investigate more.

Straw-man Proposal

We go back to slightly longer text based syntax

<element var="someId" bind-value="expr" on-event="doWork()">

The caveat is the ng-repeat syntax, which requires a parameter

<ul>
  <li bind-ng-repeat--item="items">{{item}}</li>
</ul>

Why the weird ng-repeat syntax? We want ta make sure that all bindings starting with bind- have right hand side as a valid expression. item in items is not a valid expression, it is a micro syntax. For this reason we need a way to pass the local-var-name into ng-repeat as a string literal, and not as an expression. Hence the ng-repeat--<local-var-name-literral>="expression".

Please leave your thoughts here.

Background

The reasoning behind the new syntax can be found here: https://docs.google.com/document/d/1kpuR512G1b0D8egl9245OHaG0cFh0ST0ekhD_g8sxtI/edit#heading=h.xgjl2srtytjt

@SanderElias

This comment has been minimized.

Show comment
Hide comment
@SanderElias

SanderElias Oct 31, 2014

Member

I do prefer the readability of the current proposal. The setAttribute issue can be worked around.
Dropped into the console, and did some testing. I came up with this:

   function addAttribute(element, attrName, attrValue) {
      var tmpElm = document.createElement('p');
      tmpElm.innerHTML = "<p " + attrName + "='"+attrValue+"'><p>";
      var newAttr = tmpElm.children[0].attributes[0].cloneNode(true);
      element.setAttributeNode(newAttr);
   }

Witch is pretty rough, but I checked, and it does comply to all W3C standards. Well except for enabling attributes with 'exotic' names.

And with the straw-man proposal, if a user wants to create his own ngRepeat, how would that be possible?

Member

SanderElias commented Oct 31, 2014

I do prefer the readability of the current proposal. The setAttribute issue can be worked around.
Dropped into the console, and did some testing. I came up with this:

   function addAttribute(element, attrName, attrValue) {
      var tmpElm = document.createElement('p');
      tmpElm.innerHTML = "<p " + attrName + "='"+attrValue+"'><p>";
      var newAttr = tmpElm.children[0].attributes[0].cloneNode(true);
      element.setAttributeNode(newAttr);
   }

Witch is pretty rough, but I checked, and it does comply to all W3C standards. Well except for enabling attributes with 'exotic' names.

And with the straw-man proposal, if a user wants to create his own ngRepeat, how would that be possible?

@mprobst

This comment has been minimized.

Show comment
Hide comment
@mprobst

mprobst Oct 31, 2014

Contributor

FYI for a JavaScript renamer like JSCompiler, the ng-repeat--item="items" would be easier to grok with ng-repeat="item in items". If you rename the subsequent use-sites of item, you also have to do so for the declaration. I think if you don't want microsyntaxes, you'll most likely have to go with additional attributes (ng-repeat="items" ng-repeat-var="item", could default to $item or so).

Contributor

mprobst commented Oct 31, 2014

FYI for a JavaScript renamer like JSCompiler, the ng-repeat--item="items" would be easier to grok with ng-repeat="item in items". If you rename the subsequent use-sites of item, you also have to do so for the declaration. I think if you don't want microsyntaxes, you'll most likely have to go with additional attributes (ng-repeat="items" ng-repeat-var="item", could default to $item or so).

@PascalPrecht

This comment has been minimized.

Show comment
Hide comment
@PascalPrecht

PascalPrecht Oct 31, 2014

Contributor

@SanderElias I think there are a couple of problems with that snippet:

  • It requires to work with strings and .innerHTML which leads to xss vulnerabilities. Which is also why angular works with DOM elements instead of strings because we get xss security by default
  • I'm not sure if the order of attributes is defined, which means you can't really rely on .attributes[0].cloneNode(true);. If there's more than one attribute, you might get some ugly side effects.
  • All in all it feels more like a hack

I like the bind-* and on-* syntax much more (also because I got used to it when reading all the design documents). @mhevery is the caveat with ng-repeat the only reason why you first decided to use [] and () over bind-* and on-* ?

Contributor

PascalPrecht commented Oct 31, 2014

@SanderElias I think there are a couple of problems with that snippet:

  • It requires to work with strings and .innerHTML which leads to xss vulnerabilities. Which is also why angular works with DOM elements instead of strings because we get xss security by default
  • I'm not sure if the order of attributes is defined, which means you can't really rely on .attributes[0].cloneNode(true);. If there's more than one attribute, you might get some ugly side effects.
  • All in all it feels more like a hack

I like the bind-* and on-* syntax much more (also because I got used to it when reading all the design documents). @mhevery is the caveat with ng-repeat the only reason why you first decided to use [] and () over bind-* and on-* ?

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 31, 2014

Contributor

if all of the angry tweets and blogs are to mean anything at all, it seems people don't want a new syntax anyways. easier for them if it's as similar as possible to before.

Contributor

caitp commented Oct 31, 2014

if all of the angry tweets and blogs are to mean anything at all, it seems people don't want a new syntax anyways. easier for them if it's as similar as possible to before.

@SanderElias

This comment has been minimized.

Show comment
Hide comment
@SanderElias

SanderElias Oct 31, 2014

Member

@PascalPrecht, Sure it feels like a hack, because it is one. I whipped up the snippet in a couple of minutes to show a way around the limitation of element.setAttribute(). And you can be sure on the order of attributes if you create the html-snippet under the functions control. If something like this ends up in the source, it sure needs to check the strings for XSS attacks.

@caitp creating new paths always can count on resistance. On my part, the jury is still out on this one.

Member

SanderElias commented Oct 31, 2014

@PascalPrecht, Sure it feels like a hack, because it is one. I whipped up the snippet in a couple of minutes to show a way around the limitation of element.setAttribute(). And you can be sure on the order of attributes if you create the html-snippet under the functions control. If something like this ends up in the source, it sure needs to check the strings for XSS attacks.

@caitp creating new paths always can count on resistance. On my part, the jury is still out on this one.

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 31, 2014

Contributor

the question is, what do we get out of the "new paths", if it's just change for the sake of change then it's not really doing any good. even though the grammar is technically easier to write parsers for, tools have been writing parsers for and working with angular expressions for a while now, so it seems like a moot point.

I'm really not sure we're getting any kind of "win" by making these changes.

Contributor

caitp commented Oct 31, 2014

the question is, what do we get out of the "new paths", if it's just change for the sake of change then it's not really doing any good. even though the grammar is technically easier to write parsers for, tools have been writing parsers for and working with angular expressions for a while now, so it seems like a moot point.

I'm really not sure we're getting any kind of "win" by making these changes.

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 31, 2014

Contributor

Unless we can demonstrate that it's really easier for people to use, then I would say don't even bother with it

Contributor

caitp commented Oct 31, 2014

Unless we can demonstrate that it's really easier for people to use, then I would say don't even bother with it

@SanderElias

This comment has been minimized.

Show comment
Hide comment
@SanderElias

SanderElias Oct 31, 2014

Member

@caitp Hmm, to me the win is better readable templates, and less boilerplate. The parser argument is indeed no reason whatsoever in this case. However, if the parser gets more then a few % slower as a result of the straw-man proposal, it is an valid point.

Member

SanderElias commented Oct 31, 2014

@caitp Hmm, to me the win is better readable templates, and less boilerplate. The parser argument is indeed no reason whatsoever in this case. However, if the parser gets more then a few % slower as a result of the straw-man proposal, it is an valid point.

@PascalPrecht

This comment has been minimized.

Show comment
Hide comment
@PascalPrecht

PascalPrecht Oct 31, 2014

Contributor

I'm still interested in what causes the original decision to use [] and (). There are four proposed syntaxes for template bindings but there's no official discussion on why the team decided to use [] and () over bind-* and on-*, or even one of the other two. Does anybody know why that is?

Contributor

PascalPrecht commented Oct 31, 2014

I'm still interested in what causes the original decision to use [] and (). There are four proposed syntaxes for template bindings but there's no official discussion on why the team decided to use [] and () over bind-* and on-*, or even one of the other two. Does anybody know why that is?

@otodockal

This comment has been minimized.

Show comment
Hide comment
@otodockal

otodockal Oct 31, 2014

Contributor

on-* syntax looks much more natural to use, it's similar to DOM events syntax and the current ng-event syntax.

Contributor

otodockal commented Oct 31, 2014

on-* syntax looks much more natural to use, it's similar to DOM events syntax and the current ng-event syntax.

@akircher

This comment has been minimized.

Show comment
Hide comment
@akircher

akircher Oct 31, 2014

Must you have a different left-hand syntax for binding and events?
Every event handler I have seen is a function call that contains a '()'. If Angular2 enforces this natural limitation that event handlers must be functions ( searching for a '(' and a ')' on the right-hand side), then you could use the same syntax for both binding and event. Two possibilities are:

<proposal ng-id="someId" ng-bind="expr" ng-event="doWork()">
<proposal _id="someId" _bind="expr" _event="doWork()">

As for ng-repeat, no novel ideas. I think that the bubble up event syntax (^click) will also need a work around for these problems. I would just try to keep the syntax as close to javascript as possible.

<ul>
  <li ng-for="let item of items">{{item}}</li>
</ul>

akircher commented Oct 31, 2014

Must you have a different left-hand syntax for binding and events?
Every event handler I have seen is a function call that contains a '()'. If Angular2 enforces this natural limitation that event handlers must be functions ( searching for a '(' and a ')' on the right-hand side), then you could use the same syntax for both binding and event. Two possibilities are:

<proposal ng-id="someId" ng-bind="expr" ng-event="doWork()">
<proposal _id="someId" _bind="expr" _event="doWork()">

As for ng-repeat, no novel ideas. I think that the bubble up event syntax (^click) will also need a work around for these problems. I would just try to keep the syntax as close to javascript as possible.

<ul>
  <li ng-for="let item of items">{{item}}</li>
</ul>
@PascalPrecht

This comment has been minimized.

Show comment
Hide comment
@PascalPrecht

PascalPrecht Oct 31, 2014

Contributor

@akircher yes there is a reason why angular needs a new binding syntax. In order to work with any elements (that means native and custom) a new syntax is required that unifies the layer. Angular doesn't and shouldn't know about custom elements (or custom events). I've written an article about that which tries to explain it (http://pascalprecht.github.io/2014/10/25/integrating-web-components-with-angularjs/).

Contributor

PascalPrecht commented Oct 31, 2014

@akircher yes there is a reason why angular needs a new binding syntax. In order to work with any elements (that means native and custom) a new syntax is required that unifies the layer. Angular doesn't and shouldn't know about custom elements (or custom events). I've written an article about that which tries to explain it (http://pascalprecht.github.io/2014/10/25/integrating-web-components-with-angularjs/).

@sheerun

This comment has been minimized.

Show comment
Hide comment
@sheerun

sheerun Oct 31, 2014

Hey! I paste my proposal from Google Gruups with syntax that resolves custom elements problem and doesn't break HTML attributes.

I've seen Angular plans to adopt following syntax for data binding:

<web-component [title]="exp" (close)="exp()">

Please don't break HTML syntax :( I love Angular because I can write templates for it in any templating language like SLIM or HAML or Jade (you can't do it in Ember or React, for example). Introducing non-standard characters in attributes makes templating languages unusable (as well as syntax coloring and introspection in IDE).

Also, I really don't like this syntax for passing arguments [ng-repeat|person]="people"

  • for me it's not clear what it does
  • it allows for passing only string arguments
  • both "person" and "people" are arguments to ng-repeat. Why to treat one differently?
  • it severely breaks existing syntax that developers are used to

I propose to use _ prefix for properties that need to be processed by Angular first. Then, use microsyntax instead of ugly [ng-repeat|parameter] syntax to provide parameters.

<web-component
    _string-parameter="Hello world"
    _fancy-string-parameter="Hello ${exp}"
    _one-way-bind=":exp"
    _two-way-bind=".exp"
    _on-click="exp()"
    _ng-repeat=".person in :people"
    _ng-if=".isVisible">

There are many advantages of such syntax:

  1. You don't break HTML syntax, most IDE and templating languages support leading _
  2. Attribute names only tell whether pass binding to Angular or not. Exact meaning is determined by Angular or its plugin.
  3. "templating system should be conflated with the binding system"
  4. Contrary to your current choice this syntax is extensible, and plugins can implement their own microsyntaxes.
  5. It allows for seamless WebComponent integration, as _ prefixed properties are handles by Angular before they are renamed and passed to WebComponent.
  6. I think it's lot more pleasurable to read and understand

All to all, my proposal is:

  1. Angular processes only properties beginning with _
  2. Angular supports out of the box following microsyntaxes:
    • exp - string interpolation (default, can include ES6 interpolation syntax ${exp})
    • exp() - javascript expression (like _on-click="exp()")
    • :exp - one way bind (familiar syntax!)
    • .exp - two way bind (natural syntax too)
    • exp1 in exp2 - special syntax for _ng-repeat, exp1 and exp2 are re-interpreted as microsyntaxes
  3. Plugins and future versions of Angular can define their own microsyntaxes.

Did I miss something? I beg you to consider this. I really love Angular 2.0 decisions so far, except for binding syntax.

Few additional notes:

  1. I wanted javascript expression to be the default, but I think it should be string interpolation. The same way HTML treats all attibute values as strings by default. So for example _type="text" means literally type="text", but _type=".inputType" does double binding, and _type="inputType()" evaluates an expression.
  2. This syntax also makes distinction between one-way and two-way binding. Your current choice doesn't.
  3. Plugins could create microsyntaxes from existing ones, similar to _ng-repeat's "exp1 in exp2" syntax.
  4. Such syntax is really "pluggable" and fast. Angular only reads properties beginning with _ and passes them through "middleware" set of functions with interface like call(e: HTMLElement, attribute: string, value: string).

sheerun commented Oct 31, 2014

Hey! I paste my proposal from Google Gruups with syntax that resolves custom elements problem and doesn't break HTML attributes.

I've seen Angular plans to adopt following syntax for data binding:

<web-component [title]="exp" (close)="exp()">

Please don't break HTML syntax :( I love Angular because I can write templates for it in any templating language like SLIM or HAML or Jade (you can't do it in Ember or React, for example). Introducing non-standard characters in attributes makes templating languages unusable (as well as syntax coloring and introspection in IDE).

Also, I really don't like this syntax for passing arguments [ng-repeat|person]="people"

  • for me it's not clear what it does
  • it allows for passing only string arguments
  • both "person" and "people" are arguments to ng-repeat. Why to treat one differently?
  • it severely breaks existing syntax that developers are used to

I propose to use _ prefix for properties that need to be processed by Angular first. Then, use microsyntax instead of ugly [ng-repeat|parameter] syntax to provide parameters.

<web-component
    _string-parameter="Hello world"
    _fancy-string-parameter="Hello ${exp}"
    _one-way-bind=":exp"
    _two-way-bind=".exp"
    _on-click="exp()"
    _ng-repeat=".person in :people"
    _ng-if=".isVisible">

There are many advantages of such syntax:

  1. You don't break HTML syntax, most IDE and templating languages support leading _
  2. Attribute names only tell whether pass binding to Angular or not. Exact meaning is determined by Angular or its plugin.
  3. "templating system should be conflated with the binding system"
  4. Contrary to your current choice this syntax is extensible, and plugins can implement their own microsyntaxes.
  5. It allows for seamless WebComponent integration, as _ prefixed properties are handles by Angular before they are renamed and passed to WebComponent.
  6. I think it's lot more pleasurable to read and understand

All to all, my proposal is:

  1. Angular processes only properties beginning with _
  2. Angular supports out of the box following microsyntaxes:
    • exp - string interpolation (default, can include ES6 interpolation syntax ${exp})
    • exp() - javascript expression (like _on-click="exp()")
    • :exp - one way bind (familiar syntax!)
    • .exp - two way bind (natural syntax too)
    • exp1 in exp2 - special syntax for _ng-repeat, exp1 and exp2 are re-interpreted as microsyntaxes
  3. Plugins and future versions of Angular can define their own microsyntaxes.

Did I miss something? I beg you to consider this. I really love Angular 2.0 decisions so far, except for binding syntax.

Few additional notes:

  1. I wanted javascript expression to be the default, but I think it should be string interpolation. The same way HTML treats all attibute values as strings by default. So for example _type="text" means literally type="text", but _type=".inputType" does double binding, and _type="inputType()" evaluates an expression.
  2. This syntax also makes distinction between one-way and two-way binding. Your current choice doesn't.
  3. Plugins could create microsyntaxes from existing ones, similar to _ng-repeat's "exp1 in exp2" syntax.
  4. Such syntax is really "pluggable" and fast. Angular only reads properties beginning with _ and passes them through "middleware" set of functions with interface like call(e: HTMLElement, attribute: string, value: string).
@sheerun

This comment has been minimized.

Show comment
Hide comment
@sheerun

sheerun Oct 31, 2014

Of course if for some reason Web Component uses _property, you can use __property in template.

p.s. code fragments were missing from my previous comment. they are present now.

sheerun commented Oct 31, 2014

Of course if for some reason Web Component uses _property, you can use __property in template.

p.s. code fragments were missing from my previous comment. they are present now.

@akircher

This comment has been minimized.

Show comment
Hide comment
@akircher

akircher Oct 31, 2014

@PascalPrecht I understand that Angular2 needs a generic binding/event handling syntax in order handle custom events from web components. Am I missing something else from your post? (very helpful btw)

But what I am saying is that the parser could take

<proposal ng-id="someId" ng-bind="expr" ng-event="doWork()">

and seeing that expr doesn't have a '()' and that doWork does have a '()' could rewrite this to

<proposal ng-id="someId" bind-bind="expr" on-event="doWork()">

akircher commented Oct 31, 2014

@PascalPrecht I understand that Angular2 needs a generic binding/event handling syntax in order handle custom events from web components. Am I missing something else from your post? (very helpful btw)

But what I am saying is that the parser could take

<proposal ng-id="someId" ng-bind="expr" ng-event="doWork()">

and seeing that expr doesn't have a '()' and that doWork does have a '()' could rewrite this to

<proposal ng-id="someId" bind-bind="expr" on-event="doWork()">
@oliverkra

This comment has been minimized.

Show comment
Hide comment
@oliverkra

oliverkra Oct 31, 2014

And if some native functions were rewritten to work with this new model?

HTMLInputElement.prototype._setAttribute = HTMLInputElement.prototype.setAttribute;

HTMLInputElement.prototype.setAttribute = function (attribute, value) {
    if (/\[[a-zA-Z]+\]/.test(attribute)) {
        for (var i in this.attributes) {
            if (this.attributes[i].name === attribute) {
                this.attributes[i].value = value;
            }
        }
    } else {
        this._setAttribute(attribute, value);
    }
}

var element = document.querySelector('#test');
element.setAttribute('[value]', 'New value');

oliverkra commented Oct 31, 2014

And if some native functions were rewritten to work with this new model?

HTMLInputElement.prototype._setAttribute = HTMLInputElement.prototype.setAttribute;

HTMLInputElement.prototype.setAttribute = function (attribute, value) {
    if (/\[[a-zA-Z]+\]/.test(attribute)) {
        for (var i in this.attributes) {
            if (this.attributes[i].name === attribute) {
                this.attributes[i].value = value;
            }
        }
    } else {
        this._setAttribute(attribute, value);
    }
}

var element = document.querySelector('#test');
element.setAttribute('[value]', 'New value');
@pkozlowski-opensource

This comment has been minimized.

Show comment
Hide comment
@pkozlowski-opensource

pkozlowski-opensource Oct 31, 2014

Member

@EisenbergEffect I'm probably missing things (still trying to catch up with all the design decisions in 2.0....) but my understanding was that the idea was to bind to properties and not to attributes. So I guess what you are proposing is: bind-[property name]="expression", right? Sorry if this is just nitpicking - I'm just trying to make things clear in my head.

Member

pkozlowski-opensource commented Oct 31, 2014

@EisenbergEffect I'm probably missing things (still trying to catch up with all the design decisions in 2.0....) but my understanding was that the idea was to bind to properties and not to attributes. So I guess what you are proposing is: bind-[property name]="expression", right? Sorry if this is just nitpicking - I'm just trying to make things clear in my head.

@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Oct 31, 2014

Yes. Properties. Sorry.

Note: I've deleted the original comment because it got messed up, something related to sending it through email. I've added the full version below.

On Fri, Oct 31, 2014 at 9:22 AM, Pawel Kozlowski notifications@github.com
wrote:

@EisenbergEffect https://github.com/EisenbergEffect I'm probably
missing things (still trying to catch up with all the design decisions in
2.0....) but my understanding was that he idea was to bind to properties
and not to attributes. So I guess what you are proposing is: bind-[property
name]="expression", right? Sorry if this is just nitpicking - I'm just
trying to make things clear in my head.


Reply to this email directly or view it on GitHub
#133 (comment).

Rob Eisenberg,
President - Blue Spire
www.durandaljs.com

EisenbergEffect commented Oct 31, 2014

Yes. Properties. Sorry.

Note: I've deleted the original comment because it got messed up, something related to sending it through email. I've added the full version below.

On Fri, Oct 31, 2014 at 9:22 AM, Pawel Kozlowski notifications@github.com
wrote:

@EisenbergEffect https://github.com/EisenbergEffect I'm probably
missing things (still trying to catch up with all the design decisions in
2.0....) but my understanding was that he idea was to bind to properties
and not to attributes. So I guess what you are proposing is: bind-[property
name]="expression", right? Sorry if this is just nitpicking - I'm just
trying to make things clear in my head.


Reply to this email directly or view it on GitHub
#133 (comment).

Rob Eisenberg,
President - Blue Spire
www.durandaljs.com

@PascalPrecht

This comment has been minimized.

Show comment
Hide comment
@PascalPrecht

PascalPrecht Oct 31, 2014

Contributor

I'm pretty much agreeing with @EisenbergEffect 's proposal (which again is bind-* and on-*) but i'm also very curious about what caused the decision to use [] and () in the first place. Maybe there's something we miss with bind-* and on-* that is covered with [] and ().

@EisenbergEffect Do you have a simple sample what the actual definition of such a micro syntax would look like then (from a component point of view)?

Contributor

PascalPrecht commented Oct 31, 2014

I'm pretty much agreeing with @EisenbergEffect 's proposal (which again is bind-* and on-*) but i'm also very curious about what caused the decision to use [] and () in the first place. Maybe there's something we miss with bind-* and on-* that is covered with [] and ().

@EisenbergEffect Do you have a simple sample what the actual definition of such a micro syntax would look like then (from a component point of view)?

@sheerun

This comment has been minimized.

Show comment
Hide comment
@sheerun

sheerun Oct 31, 2014

@EisenbergEffect I think we can all agree there's need for some kind of prefix / suffix to mark attributes that need to be processed by Angular into properties.

  • Current choice is [value]="something", but this is not a correct HTML attribute, and breaks lot of things I mentioned.
  • Your proposal is bind-value="something" which I think is little too verbose probably is already used by existing components
  • My proposal is _value="something"

It doesn't matter if Angular will choose to split bind-ng-repeat to two properties. What matters is, there's prefix that tells Angular to process this attribute first.

I don't think the on- prefix is good choice, because lot of components are using on-click or similar already. bind-on-click could be OK. As well as _on-click.

I think it's important to change microsyntax for double binding from exp to .exp, because the default should be the same as HTML's i.e. string (I explained it in my previous comment).

sheerun commented Oct 31, 2014

@EisenbergEffect I think we can all agree there's need for some kind of prefix / suffix to mark attributes that need to be processed by Angular into properties.

  • Current choice is [value]="something", but this is not a correct HTML attribute, and breaks lot of things I mentioned.
  • Your proposal is bind-value="something" which I think is little too verbose probably is already used by existing components
  • My proposal is _value="something"

It doesn't matter if Angular will choose to split bind-ng-repeat to two properties. What matters is, there's prefix that tells Angular to process this attribute first.

I don't think the on- prefix is good choice, because lot of components are using on-click or similar already. bind-on-click could be OK. As well as _on-click.

I think it's important to change microsyntax for double binding from exp to .exp, because the default should be the same as HTML's i.e. string (I explained it in my previous comment).

@PascalPrecht

This comment has been minimized.

Show comment
Hide comment
@PascalPrecht

PascalPrecht Oct 31, 2014

Contributor

@sheerun

@EisenbergEffect I think we can all agree there's need for some kind of prefix / suffix

  • Yes, not necessarily a prefix/suffix but a syntax that unifies custom attributes/events in a declarative DSL. And yes we all agree on it, that's why this change has been introduced in the first place.

to mark attributes that need to be processed by Angular into properties.

  • Angular doesn't "process attributes into properties". It either binds to properties or attributes depending on the particular attribute and if it's reflected as property or not. So binding to an attribute is rather a fallback (as far as I understood the design documents)

Your proposal is bind-value="something" which I think is little too verbose probably is already used by existing components

  • I think bind- and on- are pretty straight forward.

It doesn't matter if Angular will choose to split bind-ng-repeat to two properties.

  • It actually does matter in order to have a simple DSL do express such things.

bind-on-click could be OK

  • IMO that's rather not a good choice, since we don't really bind to events. We listen to them.

I think it's important to change microsyntax for double binding from exp to .exp, because the default should be the same as HTML's i.e. string (I explained it in my previous comment).

  • I find .whatever rather confusing since that is what people know as CSS selectors.
Contributor

PascalPrecht commented Oct 31, 2014

@sheerun

@EisenbergEffect I think we can all agree there's need for some kind of prefix / suffix

  • Yes, not necessarily a prefix/suffix but a syntax that unifies custom attributes/events in a declarative DSL. And yes we all agree on it, that's why this change has been introduced in the first place.

to mark attributes that need to be processed by Angular into properties.

  • Angular doesn't "process attributes into properties". It either binds to properties or attributes depending on the particular attribute and if it's reflected as property or not. So binding to an attribute is rather a fallback (as far as I understood the design documents)

Your proposal is bind-value="something" which I think is little too verbose probably is already used by existing components

  • I think bind- and on- are pretty straight forward.

It doesn't matter if Angular will choose to split bind-ng-repeat to two properties.

  • It actually does matter in order to have a simple DSL do express such things.

bind-on-click could be OK

  • IMO that's rather not a good choice, since we don't really bind to events. We listen to them.

I think it's important to change microsyntax for double binding from exp to .exp, because the default should be the same as HTML's i.e. string (I explained it in my previous comment).

  • I find .whatever rather confusing since that is what people know as CSS selectors.
@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Oct 31, 2014

I'm wondering if we can take a muli-faceted approach here.

For the core binding capability:

1.bind-property="{{expression}}" - default binding behavior
2.on-event="{{expression}}" - add event handler
3.${expression} - string interpolation (aligns with ES6 syntax)
4. Support a microsyntax hook that would allow directives like ng-repeat to translate ng-repeat="person in people" into two attributes: bind-ng-repeat="people" ng-repeat-local="person" once during template compilation.

On top of this core layer, add a backwards compatibility/convenience layer:

  1. Support property="{{expression}}" for convenience and backwards compatibility with 1.x. During compilation this will result in the removal of the attribute. A special debug mode for the compiler would re-write it as bind-property="expression" so that it could be seen in the DOM inspector. In production the attribute would be absent to avoid the cost of re-writing.
  2. Support {{expression}} inside of HTML content. This should be treated as a string interpolation exactly the same as ${expression} for backwards compatibility. (Opt-in only via a config setting on the templating engine.)
  3. Support an optional plugin to Angular 2.0 which contains a few directives like ng-click. This would be for backwards compatibility only. These directive would use the microsyntax hook to translate themselves into the new syntax.
  4. Upon release of ng2.0 mark the {{expression}} for html content only as obsolete and the optional ng-click, etc. directives as obsolete. This is planned obsolescence from the get go. This will help people to incrementally port but give them a timeline to upgrade to the new syntax after they get their app up and running.

Support a generalized mechanism for binding options, built into the expression syntax.

  1. An example of a one time binding might be: property="{{some.property & one_time}}"
  2. An example of a custom trigger for a two-way binding might be <input value="{{some.property & trigger:'blur'}}" />
  3. Note that binding options are similar to filters. While filters act on the output of the expression by transforming it in various ways, binding options would act on the binding object itself, allowing the manipulation of it directly.

Note that none of these proposals support directionality in bindings. If we are to support one-way and two-way binding, I would recommend the following:

  1. bind- and {{}} expressions use the "default binding" for a given property. By default this means one-way binding for everything except form control values, which default to two-way.
  2. directive properties would default to one-way but the developer could change the default for a given property using metadata annotations
  3. all defaults could be overridden on a case-by-case basis using the binding options mechanism described above i.e. property="{{some.property & one_time}}"

EisenbergEffect commented Oct 31, 2014

I'm wondering if we can take a muli-faceted approach here.

For the core binding capability:

1.bind-property="{{expression}}" - default binding behavior
2.on-event="{{expression}}" - add event handler
3.${expression} - string interpolation (aligns with ES6 syntax)
4. Support a microsyntax hook that would allow directives like ng-repeat to translate ng-repeat="person in people" into two attributes: bind-ng-repeat="people" ng-repeat-local="person" once during template compilation.

On top of this core layer, add a backwards compatibility/convenience layer:

  1. Support property="{{expression}}" for convenience and backwards compatibility with 1.x. During compilation this will result in the removal of the attribute. A special debug mode for the compiler would re-write it as bind-property="expression" so that it could be seen in the DOM inspector. In production the attribute would be absent to avoid the cost of re-writing.
  2. Support {{expression}} inside of HTML content. This should be treated as a string interpolation exactly the same as ${expression} for backwards compatibility. (Opt-in only via a config setting on the templating engine.)
  3. Support an optional plugin to Angular 2.0 which contains a few directives like ng-click. This would be for backwards compatibility only. These directive would use the microsyntax hook to translate themselves into the new syntax.
  4. Upon release of ng2.0 mark the {{expression}} for html content only as obsolete and the optional ng-click, etc. directives as obsolete. This is planned obsolescence from the get go. This will help people to incrementally port but give them a timeline to upgrade to the new syntax after they get their app up and running.

Support a generalized mechanism for binding options, built into the expression syntax.

  1. An example of a one time binding might be: property="{{some.property & one_time}}"
  2. An example of a custom trigger for a two-way binding might be <input value="{{some.property & trigger:'blur'}}" />
  3. Note that binding options are similar to filters. While filters act on the output of the expression by transforming it in various ways, binding options would act on the binding object itself, allowing the manipulation of it directly.

Note that none of these proposals support directionality in bindings. If we are to support one-way and two-way binding, I would recommend the following:

  1. bind- and {{}} expressions use the "default binding" for a given property. By default this means one-way binding for everything except form control values, which default to two-way.
  2. directive properties would default to one-way but the developer could change the default for a given property using metadata annotations
  3. all defaults could be overridden on a case-by-case basis using the binding options mechanism described above i.e. property="{{some.property & one_time}}"
@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 31, 2014

Contributor

@EisenbergEffect I feel like the "more than one way to do the thing" scenario is something we probably want to avoid...

Unfortunately, we obviously don't want to stick with exactly the original style either, but I think we should definitely try to minimize the size of the bridge that people have to cross in order to learn NewFangledAngular

Contributor

caitp commented Oct 31, 2014

@EisenbergEffect I feel like the "more than one way to do the thing" scenario is something we probably want to avoid...

Unfortunately, we obviously don't want to stick with exactly the original style either, but I think we should definitely try to minimize the size of the bridge that people have to cross in order to learn NewFangledAngular

@hfjallemark

This comment has been minimized.

Show comment
Hide comment
@hfjallemark

hfjallemark Oct 31, 2014

I would look at the "more than one way to do the thing" as an optional backward compatibility layered on top. Meaning; support and educate the ideal 2.0 syntax in the core but provide extensibility points to allow layering different syntaxes on top to ease migration paths for developers with large 1.x codebases.

hfjallemark commented Oct 31, 2014

I would look at the "more than one way to do the thing" as an optional backward compatibility layered on top. Meaning; support and educate the ideal 2.0 syntax in the core but provide extensibility points to allow layering different syntaxes on top to ease migration paths for developers with large 1.x codebases.

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 31, 2014

Contributor

it means we have an extra set of duplicate functionality to support, and we also confuse users who aren't sure which one to use in their apps. It's no good, strongly advise against it.

Contributor

caitp commented Oct 31, 2014

it means we have an extra set of duplicate functionality to support, and we also confuse users who aren't sure which one to use in their apps. It's no good, strongly advise against it.

@pkozlowski-opensource

This comment has been minimized.

Show comment
Hide comment
@pkozlowski-opensource

pkozlowski-opensource Oct 31, 2014

Member

I tend to agree with @caitp here - those compatibility layers don't come for free (both in terms of initial coding, maintenance, mental burden for users etc.). Instead of providing a compatibility layer for, say, ng-click and the like it would be IMO better to come up with a migration tool that would help with translating existing templates.

But I would really prefer that we figure out the best syntax for 2.0 first and cover the migration story afterwards.

Member

pkozlowski-opensource commented Oct 31, 2014

I tend to agree with @caitp here - those compatibility layers don't come for free (both in terms of initial coding, maintenance, mental burden for users etc.). Instead of providing a compatibility layer for, say, ng-click and the like it would be IMO better to come up with a migration tool that would help with translating existing templates.

But I would really prefer that we figure out the best syntax for 2.0 first and cover the migration story afterwards.

@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Oct 31, 2014

This is what you teach people:

  • property="{{expression}}" - default binding behavior
  • on-event="{{expression}}" - add event handler
  • ${expression} - string interpolation

That's it. Then, under the hood, you remove the expressions from the DOM to prevent the various web component issues, etc. In debug mode only, you add them back as bind- attributes so they can be seen when inspecting the DOM.

You then add a section to your documentation geared towards existing Angular 1.x users that explains that they can use {{expression}} for string interpolation in html content by turning that on, but it's planned for obsolescence in 20xx. The preferred method is ${expression}. You also tell them that there is a set of optional directives they can drop in that enable ng-click etc. which are also planned for obsolescence in 20xx. But these things are provided to ease their migration experience. You then, side-by-side, explain how the temporary migration-purposed directives map to the new system.

In your documentation you have an "advanced" section that explains how to create directives with microsyntax. You can also explain that everything gets converted to bind- under the hood and thus it can be used directly if desired.

It's trivial to implement the fallback syntax and attribute re-writing. It's also not much code to maintain and would be planned for removal in 20xx from the beginning.

EisenbergEffect commented Oct 31, 2014

This is what you teach people:

  • property="{{expression}}" - default binding behavior
  • on-event="{{expression}}" - add event handler
  • ${expression} - string interpolation

That's it. Then, under the hood, you remove the expressions from the DOM to prevent the various web component issues, etc. In debug mode only, you add them back as bind- attributes so they can be seen when inspecting the DOM.

You then add a section to your documentation geared towards existing Angular 1.x users that explains that they can use {{expression}} for string interpolation in html content by turning that on, but it's planned for obsolescence in 20xx. The preferred method is ${expression}. You also tell them that there is a set of optional directives they can drop in that enable ng-click etc. which are also planned for obsolescence in 20xx. But these things are provided to ease their migration experience. You then, side-by-side, explain how the temporary migration-purposed directives map to the new system.

In your documentation you have an "advanced" section that explains how to create directives with microsyntax. You can also explain that everything gets converted to bind- under the hood and thus it can be used directly if desired.

It's trivial to implement the fallback syntax and attribute re-writing. It's also not much code to maintain and would be planned for removal in 20xx from the beginning.

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 31, 2014

Contributor

I don't think we should be doing any re-arranging under the hood here. It's making things worse, rather than better. Ideally, "what you write is what you get", there should be a limited set of constructs that you can write, but they should be reasonably powerful, so that you can express a meaningful application with them.

Less is more here, imho. Minimizing the burden on (new and old) users, and minimizing the cost of maintaining the framework, is a big win.

Contributor

caitp commented Oct 31, 2014

I don't think we should be doing any re-arranging under the hood here. It's making things worse, rather than better. Ideally, "what you write is what you get", there should be a limited set of constructs that you can write, but they should be reasonably powerful, so that you can express a meaningful application with them.

Less is more here, imho. Minimizing the burden on (new and old) users, and minimizing the cost of maintaining the framework, is a big win.

@Francisc

This comment has been minimized.

Show comment
Hide comment
@Francisc

Francisc Oct 31, 2014

I didn't like the #, [], () syntax because it makes markup not look like markup and because it's another abstract convention you need to learn, similar to directives' @, =, & for example. I feel the same about adding anything that doesn't start with [a-z], like underscores.

I agree with Caitlin, there should be some sort of gain by changing this part of Angular and I know there's been a lot of criticism about the decision to change this part. Frankly, I've never felt this needs addressing.

Having a string that says what it does is better than an abstract notation.
Using --item is also kind of abstract and very "singular" in the case of ngRepeat.

Francisc commented Oct 31, 2014

I didn't like the #, [], () syntax because it makes markup not look like markup and because it's another abstract convention you need to learn, similar to directives' @, =, & for example. I feel the same about adding anything that doesn't start with [a-z], like underscores.

I agree with Caitlin, there should be some sort of gain by changing this part of Angular and I know there's been a lot of criticism about the decision to change this part. Frankly, I've never felt this needs addressing.

Having a string that says what it does is better than an abstract notation.
Using --item is also kind of abstract and very "singular" in the case of ngRepeat.

@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Oct 31, 2014

My proposal attempts to solve both the technical issues at hand while also dealing with the migration story which the rather large Angular 1.x community is asking for. As far as I know, it is the only proposal from either inside or outside the team that attempts to handle both of these needs. The syntax is also the simplest of any of the proposals and it aligns nicely with Polymer as well.

Let's look at what Polymer does:

  • attribute="{{expression}}" - default binding behavior
  • on-event="{{expression}}" - add event handler
  • {{expression}} - string interpolation
  • _attribute="{{expression}}" - encode attribute for edge cases (which will likely go away in the next year)

My proposal changes {{}} to ${} in order to make the stringification explicit. This is necessary since we bind to properties rather than attributes. My proposal also recommends using the more meaningful bind- rather than _ for attribute name encoding, when required. What I'm proposing also improves the debugging story by re-writing the expressions in debug mode.

It's really very little work for us to do this.

EisenbergEffect commented Oct 31, 2014

My proposal attempts to solve both the technical issues at hand while also dealing with the migration story which the rather large Angular 1.x community is asking for. As far as I know, it is the only proposal from either inside or outside the team that attempts to handle both of these needs. The syntax is also the simplest of any of the proposals and it aligns nicely with Polymer as well.

Let's look at what Polymer does:

  • attribute="{{expression}}" - default binding behavior
  • on-event="{{expression}}" - add event handler
  • {{expression}} - string interpolation
  • _attribute="{{expression}}" - encode attribute for edge cases (which will likely go away in the next year)

My proposal changes {{}} to ${} in order to make the stringification explicit. This is necessary since we bind to properties rather than attributes. My proposal also recommends using the more meaningful bind- rather than _ for attribute name encoding, when required. What I'm proposing also improves the debugging story by re-writing the expressions in debug mode.

It's really very little work for us to do this.

@DeborahK

This comment has been minimized.

Show comment
Hide comment
@DeborahK

DeborahK Dec 31, 2014

Because of Angular's current expressiveness and approachability, there has been an influx of people trying out Web development that have not before. This includes lots of devs from the Microsoft community that "hated" Web development, PHP devs, and Web designers that found they could understand Angular.
I believe that this approachability is due to Angular's current syntax, which is light on the syntax and minimizes symbols such as braces and parens. The more syntax that we introduce ... the less approachable and more error prone it will become.
As a Web developer since the "Internet bubble" in the '90's and a speaker/training, I see people struggle with technologies. Yet with the current version of Angular, I see them be successful with very little in the way of training/introduction. The more "syntax" we add here the less expressive and approachable it becomes.

DeborahK commented Dec 31, 2014

Because of Angular's current expressiveness and approachability, there has been an influx of people trying out Web development that have not before. This includes lots of devs from the Microsoft community that "hated" Web development, PHP devs, and Web designers that found they could understand Angular.
I believe that this approachability is due to Angular's current syntax, which is light on the syntax and minimizes symbols such as braces and parens. The more syntax that we introduce ... the less approachable and more error prone it will become.
As a Web developer since the "Internet bubble" in the '90's and a speaker/training, I see people struggle with technologies. Yet with the current version of Angular, I see them be successful with very little in the way of training/introduction. The more "syntax" we add here the less expressive and approachable it becomes.

@mvolkmann

This comment has been minimized.

Show comment
Hide comment
@mvolkmann

mvolkmann Dec 31, 2014

I agree with Deborah!

On Wed, Dec 31, 2014 at 12:58 PM, Deborah Kurata notifications@github.com
wrote:

Because of Angular's current expressiveness and approachability, there has
been an influx of people trying out Web development that have not before.
This includes lots of devs from the Microsoft community that "hated" Web
development, PHP devs, and Web designers that found they could understand
Angular.
I believe that this approachability is due to Angular's current syntax,
which is light on the syntax and minimizes symbols such as braces and
parens. The more syntax that we introduce ... the less approachable and
more error prone it will become.
As a Web developer since the "Internet bubble" in the '90's and a
speaker/training, I see people struggle with technologies. Yet with the
current version of Angular, I see them be successful with very little in
the way of training/introduction. The more "syntax" we add here the less
expressive and approachable it becomes.


Reply to this email directly or view it on GitHub
#133 (comment).

R. Mark Volkmann
Object Computing, Inc.

mvolkmann commented Dec 31, 2014

I agree with Deborah!

On Wed, Dec 31, 2014 at 12:58 PM, Deborah Kurata notifications@github.com
wrote:

Because of Angular's current expressiveness and approachability, there has
been an influx of people trying out Web development that have not before.
This includes lots of devs from the Microsoft community that "hated" Web
development, PHP devs, and Web designers that found they could understand
Angular.
I believe that this approachability is due to Angular's current syntax,
which is light on the syntax and minimizes symbols such as braces and
parens. The more syntax that we introduce ... the less approachable and
more error prone it will become.
As a Web developer since the "Internet bubble" in the '90's and a
speaker/training, I see people struggle with technologies. Yet with the
current version of Angular, I see them be successful with very little in
the way of training/introduction. The more "syntax" we add here the less
expressive and approachable it becomes.


Reply to this email directly or view it on GitHub
#133 (comment).

R. Mark Volkmann
Object Computing, Inc.

@e-oz

This comment has been minimized.

Show comment
Hide comment
@e-oz

e-oz Dec 31, 2014

I agree with @DeborahK but also I think programmers should be ready to learn new things. Whole life. And even if technology is not as easy to understand as PHP for newcomers, it still can be as powerful and popular in enterprise software world as Java. I'm sure team can find good balance :)

Happy New Year! 💫

e-oz commented Dec 31, 2014

I agree with @DeborahK but also I think programmers should be ready to learn new things. Whole life. And even if technology is not as easy to understand as PHP for newcomers, it still can be as powerful and popular in enterprise software world as Java. I'm sure team can find good balance :)

Happy New Year! 💫

@nilskp

This comment has been minimized.

Show comment
Hide comment
@nilskp

nilskp Jan 3, 2015

Not sure if this is a recent change, prompted by this, but Jade seems to support both parentheses and brackets as attributes.
http://jade-lang.com/demo/

nilskp commented Jan 3, 2015

Not sure if this is a recent change, prompted by this, but Jade seems to support both parentheses and brackets as attributes.
http://jade-lang.com/demo/

@pnazeran

This comment has been minimized.

Show comment
Hide comment
@pnazeran

pnazeran Jan 13, 2015

  • I agree with DeborahK: expressive is better than syntactical
  • but syntax could mean shorter code too. So it is a compromise between typing and approachability

$scope variables may appear inside the brackets <> or outside.

  • Outside
    • the content of ${...} can be assumed a java-script expression as all binding would be one-way.
    • $ reminds most of the linux command prompt, where expressions are entered, so I prefer it to {{...}}
    • these are the general use cases I can think of:
      • Hello Visitor
      • Hello ${user_name}
      • Hello ${(a == b ? user_name : 'Visitor')}
      • Hello ${myFactory.getUserName()}
  • Inside: Attributes
    I want to second kpentchev's proposal for attribute assignments, but without the ng- at the beginning. Something like:
    • on-click="..." (event binding)
    • sync-value="..." (two-way binding of the value property)
    • bind-value="..." (one-way binding of the value property)
    • set-value="..." (once off ...)
    • value = "..." for string literals

As was pointed out, it is important that:

The syntax must clearly distinguish between 1) string literal; 2) expression (binding); 3) expression (events) 4) declaration of variables.

  • on-click: always an expression:
    • on-click = "click()"
    • on-click = "text.style = 'bold'"
  • sync-value: a variable name otherwise two-way binding won't work.
  • bind-value: a variable name or expression, so can be processed as expression
    • bind-value = "user_name"
    • bind-value = "myFactory.getUserName()"
  • set-value is just a special case of bind-value.

There may not be any ambiguity regarding string-literals, expressions, etc. as kpentchev's proposal clarifies that for attributes, and takes care of one-way and two-way

pnazeran commented Jan 13, 2015

  • I agree with DeborahK: expressive is better than syntactical
  • but syntax could mean shorter code too. So it is a compromise between typing and approachability

$scope variables may appear inside the brackets <> or outside.

  • Outside
    • the content of ${...} can be assumed a java-script expression as all binding would be one-way.
    • $ reminds most of the linux command prompt, where expressions are entered, so I prefer it to {{...}}
    • these are the general use cases I can think of:
      • Hello Visitor
      • Hello ${user_name}
      • Hello ${(a == b ? user_name : 'Visitor')}
      • Hello ${myFactory.getUserName()}
  • Inside: Attributes
    I want to second kpentchev's proposal for attribute assignments, but without the ng- at the beginning. Something like:
    • on-click="..." (event binding)
    • sync-value="..." (two-way binding of the value property)
    • bind-value="..." (one-way binding of the value property)
    • set-value="..." (once off ...)
    • value = "..." for string literals

As was pointed out, it is important that:

The syntax must clearly distinguish between 1) string literal; 2) expression (binding); 3) expression (events) 4) declaration of variables.

  • on-click: always an expression:
    • on-click = "click()"
    • on-click = "text.style = 'bold'"
  • sync-value: a variable name otherwise two-way binding won't work.
  • bind-value: a variable name or expression, so can be processed as expression
    • bind-value = "user_name"
    • bind-value = "myFactory.getUserName()"
  • set-value is just a special case of bind-value.

There may not be any ambiguity regarding string-literals, expressions, etc. as kpentchev's proposal clarifies that for attributes, and takes care of one-way and two-way

@circlingthesun

This comment has been minimized.

Show comment
Hide comment
@circlingthesun

circlingthesun Jan 26, 2015

@EisenbergEffect's syntax for Aurelia looks really nice.

circlingthesun commented Jan 26, 2015

@EisenbergEffect's syntax for Aurelia looks really nice.

@gdi2290

This comment has been minimized.

Show comment
Hide comment
@gdi2290

gdi2290 Jan 26, 2015

Member

+1 for Aurelia

Member

gdi2290 commented Jan 26, 2015

+1 for Aurelia

@PascalPrecht

This comment has been minimized.

Show comment
Hide comment
@PascalPrecht

PascalPrecht Jan 26, 2015

Contributor

I think all syntaxes by Aurelia have already been proposed here by @EisenbergEffect. Please stop voting them up here.

Contributor

PascalPrecht commented Jan 26, 2015

I think all syntaxes by Aurelia have already been proposed here by @EisenbergEffect. Please stop voting them up here.

@martinmcwhorter

This comment has been minimized.

Show comment
Hide comment
@martinmcwhorter

martinmcwhorter Feb 3, 2015

This may be late to the conversation, but I would like type annotations available in templates:

<form ng-type="vm.person: IPerson">
    <input type=text ng-model="vm.person.firstName" />
    <input type=text ng-model="vm.person.lastName" />
</form>

This could then be validated by an IDE or build time gulp/grunt task.

AtScript or TypeScript:

export interface IPerson {
    firstName: string;
    lastName: string;
}

The ng-type attribute could be removed from the template by the build task, as it would only be needed for development and build. Otherwise, it would get ignored in production.

Could this help IDEs with other issues with trying to understand angular's template system?

martinmcwhorter commented Feb 3, 2015

This may be late to the conversation, but I would like type annotations available in templates:

<form ng-type="vm.person: IPerson">
    <input type=text ng-model="vm.person.firstName" />
    <input type=text ng-model="vm.person.lastName" />
</form>

This could then be validated by an IDE or build time gulp/grunt task.

AtScript or TypeScript:

export interface IPerson {
    firstName: string;
    lastName: string;
}

The ng-type attribute could be removed from the template by the build task, as it would only be needed for development and build. Otherwise, it would get ignored in production.

Could this help IDEs with other issues with trying to understand angular's template system?

@tonypee

This comment has been minimized.

Show comment
Hide comment
@tonypee

tonypee Feb 17, 2015

I think the reason people are voting up the Rob's dot syntax, is that it looks good. Semantically i think it works? (it seems as flexible as [] or ()) So, i would implore the angular 2 team (mhevery?) To please listen to people's suggestions. Frankly, I've just seen the video on the 'alpha' release, and the syntax looks visually terrible. I hope never to have to write with that syntax

tonypee commented Feb 17, 2015

I think the reason people are voting up the Rob's dot syntax, is that it looks good. Semantically i think it works? (it seems as flexible as [] or ()) So, i would implore the angular 2 team (mhevery?) To please listen to people's suggestions. Frankly, I've just seen the video on the 'alpha' release, and the syntax looks visually terrible. I hope never to have to write with that syntax

@e-oz

This comment has been minimized.

Show comment
Hide comment
@e-oz

e-oz Feb 17, 2015

@tonypee I see only 2 votes and compared with size of thread is nothing.

I wonder why ngnl presentation and current docs about templates still promoting []()# as parts of new syntax, when opening post in this thread contains

element.setAttribute('[foo]', 'exp') does not work

and, especially

SVG requires valid XML and []()# is not valid XML.

If these problems are solved somehow and we just don't know - please let us know.

e-oz commented Feb 17, 2015

@tonypee I see only 2 votes and compared with size of thread is nothing.

I wonder why ngnl presentation and current docs about templates still promoting []()# as parts of new syntax, when opening post in this thread contains

element.setAttribute('[foo]', 'exp') does not work

and, especially

SVG requires valid XML and []()# is not valid XML.

If these problems are solved somehow and we just don't know - please let us know.

@tonypee

This comment has been minimized.

Show comment
Hide comment
@tonypee

tonypee Feb 17, 2015

@jamm the 'voting' followed positive multiple comments support a prefix/suffix style of defining binding. Originally, @EisenbergEffect suggested bind- on- etc. with 4 people supporting (@PascalPrecht, @SanderElias, @donaldpipowitch, @yamafactory). Recently the dot suffix (which @mhevery suggested is semantically the same) has positive support of:
@DeborahK, @Awk34 , Alxandr, @akircher, @nborelli, @circlingthesun, @gdi2290, and now me

It seems that readability & usability might be taking a backseat to perceived restrictions. I feel the comments suggest that people would *rather a more elegant syntax.

I'll be interested to see some more full examples of the () [] syntax, as i can understand change is hard. But, initially perception is important too - and the . syntax looks more elegant and readable

tonypee commented Feb 17, 2015

@jamm the 'voting' followed positive multiple comments support a prefix/suffix style of defining binding. Originally, @EisenbergEffect suggested bind- on- etc. with 4 people supporting (@PascalPrecht, @SanderElias, @donaldpipowitch, @yamafactory). Recently the dot suffix (which @mhevery suggested is semantically the same) has positive support of:
@DeborahK, @Awk34 , Alxandr, @akircher, @nborelli, @circlingthesun, @gdi2290, and now me

It seems that readability & usability might be taking a backseat to perceived restrictions. I feel the comments suggest that people would *rather a more elegant syntax.

I'll be interested to see some more full examples of the () [] syntax, as i can understand change is hard. But, initially perception is important too - and the . syntax looks more elegant and readable

@gdi2290

This comment has been minimized.

Show comment
Hide comment
@gdi2290

gdi2290 Feb 17, 2015

Member

@tonypee Actually if we're voting or anything I'll withdraw mine. I'm in favor of the current syntax using (event)="exp" and [property]="val" after using angular2 to create a todo app it I found it's pretty clear. Keep in mind you can also use bind-, on-, and def with angular2's current syntax since ()[]# are considered shorthand and element.setAttribute('[foo]', 'exp') problem is solved by using their facade API for DOM aka using DOM.setAttribute(element, '[foo]', 'exp')

Tipe CMS

Member

gdi2290 commented Feb 17, 2015

@tonypee Actually if we're voting or anything I'll withdraw mine. I'm in favor of the current syntax using (event)="exp" and [property]="val" after using angular2 to create a todo app it I found it's pretty clear. Keep in mind you can also use bind-, on-, and def with angular2's current syntax since ()[]# are considered shorthand and element.setAttribute('[foo]', 'exp') problem is solved by using their facade API for DOM aka using DOM.setAttribute(element, '[foo]', 'exp')

Tipe CMS

@Awk34

This comment has been minimized.

Show comment
Hide comment
@Awk34

Awk34 Feb 17, 2015

@gdi2290 Thanks for the example code. I think I agree with you. As long as a new can use bind-property="val" as to make the syntax easier for beginners, and an experienced user can use the shorthand [property]="val" for more readable and terse code, I think it's a good solution.

Awk34 commented Feb 17, 2015

@gdi2290 Thanks for the example code. I think I agree with you. As long as a new can use bind-property="val" as to make the syntax easier for beginners, and an experienced user can use the shorthand [property]="val" for more readable and terse code, I think it's a good solution.

@DavidSouther

This comment has been minimized.

Show comment
Hide comment
@DavidSouther

DavidSouther Feb 17, 2015

I like the []()# syntax markers aesthetically, but I would like confirmation or refutation from @mhevery @IgorMinar et al that they will not break SVG or broader XML interoperability.

DavidSouther commented Feb 17, 2015

I like the []()# syntax markers aesthetically, but I would like confirmation or refutation from @mhevery @IgorMinar et al that they will not break SVG or broader XML interoperability.

@petebacondarwin

This comment has been minimized.

Show comment
Hide comment
@petebacondarwin

petebacondarwin Feb 17, 2015

Member

Read the summary of the syntax here: https://docs.google.com/document/d/1HHy_zPLGqJj0bHMiWPzPCxn1pO5GlOYwmv-qGgl4f_s/edit#heading=h.4w4k319ilnp8

There are two forms - shorthand (all these [...], (...) and so on) and the canonical form (bind-, on- and so on). The canonical forms are basically what you could use if you are using Angular 2 inside SVG or X(HT)ML documents.

Member

petebacondarwin commented Feb 17, 2015

Read the summary of the syntax here: https://docs.google.com/document/d/1HHy_zPLGqJj0bHMiWPzPCxn1pO5GlOYwmv-qGgl4f_s/edit#heading=h.4w4k319ilnp8

There are two forms - shorthand (all these [...], (...) and so on) and the canonical form (bind-, on- and so on). The canonical forms are basically what you could use if you are using Angular 2 inside SVG or X(HT)ML documents.

@DavidSouther

This comment has been minimized.

Show comment
Hide comment
@DavidSouther

DavidSouther Feb 17, 2015

@petebacondarwin That document has evolved quite a bit since I last looked at it :) Thanks for pointing out the updates.

DavidSouther commented Feb 17, 2015

@petebacondarwin That document has evolved quite a bit since I last looked at it :) Thanks for pointing out the updates.

@e-oz

This comment has been minimized.

Show comment
Hide comment
@e-oz

e-oz Feb 17, 2015

thanks @petebacondarwin, finally it's resolved :)

e-oz commented Feb 17, 2015

thanks @petebacondarwin, finally it's resolved :)

@JeroMiya

This comment has been minimized.

Show comment
Hide comment
@JeroMiya

JeroMiya Feb 18, 2015

@DavidSouther It is indeed true that the []()# attribute syntax is incompatible in an application/xhtml+xml document. Dots are, however, valid - e.g. on.click="foo".

I do not agree that the []()# attribute syntax is more readable than the prefix proposal. I think using sigils in general in place of keywords results in things that are terse but ultimately harder to comprehend. I feel the same way about sigil-heavy programming languages.

I also strongly recommend against having two different ways of writing templates. This is really confusing to new developers and results in inconsistent and hard-to-read templates as some developers write them one way, and others write them another. It reminds me of how some developers would use data-ng-* and others just ng-*, and the three different ways of doing dependency injection (one of which I had to ban, despite it being used in EVERY sample and talk on the internet). In this case I would have to ban the []()# syntax as our xml meta-templating tools wouldn't be able to parse them.

Given the lack of xml/SVG compatibility, I would say that the []()# syntax simply fails to meet the constraints, and should be eliminated altogether in favor of the prefix proposal.

JeroMiya commented Feb 18, 2015

@DavidSouther It is indeed true that the []()# attribute syntax is incompatible in an application/xhtml+xml document. Dots are, however, valid - e.g. on.click="foo".

I do not agree that the []()# attribute syntax is more readable than the prefix proposal. I think using sigils in general in place of keywords results in things that are terse but ultimately harder to comprehend. I feel the same way about sigil-heavy programming languages.

I also strongly recommend against having two different ways of writing templates. This is really confusing to new developers and results in inconsistent and hard-to-read templates as some developers write them one way, and others write them another. It reminds me of how some developers would use data-ng-* and others just ng-*, and the three different ways of doing dependency injection (one of which I had to ban, despite it being used in EVERY sample and talk on the internet). In this case I would have to ban the []()# syntax as our xml meta-templating tools wouldn't be able to parse them.

Given the lack of xml/SVG compatibility, I would say that the []()# syntax simply fails to meet the constraints, and should be eliminated altogether in favor of the prefix proposal.

@ldiego08

This comment has been minimized.

Show comment
Hide comment
@ldiego08

ldiego08 Mar 6, 2015

After reading the thread, these are my favorite suggestions:

  • Period notation for attributes.
  • JS object-like expressions for complex directives like ng-repeat.
  • Namespacing for prefixing attributes.
  • ${} enclosure for string interpolation.

Based on that, this is what I'm thinking of:

Template With Property Binding
<ng:template>
    <div ng:bind="{ title: expression1 }">
        <p>${expression2}</p>
    </div>
</ng:template>
Repeating, Event Binding, etc.
<ng:template>
    <ul>
        <li ng:for="{ each: 'item', in: items }">
            <span>${item.foo}</span>
            <button ng:on.click="deleteItem(item.id)">X</button>
        </li>
    </ul>
</ng:template>
Multi-line Lovers Compatible
<ng:template>
    <div ng:bind="{
            title: expression1,
            foo: expression2
         }">
        <ul>
            <li ng:for="{
                   each: 'item',
                   in: items
                }">
                <span>${item.foo}</span>
                <button ng:on.click="deleteItem(item.id)"
                        ng:on.blur="doSomething()">
                    X
                </button>
            </li>
    </div>
</ng:template>

ldiego08 commented Mar 6, 2015

After reading the thread, these are my favorite suggestions:

  • Period notation for attributes.
  • JS object-like expressions for complex directives like ng-repeat.
  • Namespacing for prefixing attributes.
  • ${} enclosure for string interpolation.

Based on that, this is what I'm thinking of:

Template With Property Binding
<ng:template>
    <div ng:bind="{ title: expression1 }">
        <p>${expression2}</p>
    </div>
</ng:template>
Repeating, Event Binding, etc.
<ng:template>
    <ul>
        <li ng:for="{ each: 'item', in: items }">
            <span>${item.foo}</span>
            <button ng:on.click="deleteItem(item.id)">X</button>
        </li>
    </ul>
</ng:template>
Multi-line Lovers Compatible
<ng:template>
    <div ng:bind="{
            title: expression1,
            foo: expression2
         }">
        <ul>
            <li ng:for="{
                   each: 'item',
                   in: items
                }">
                <span>${item.foo}</span>
                <button ng:on.click="deleteItem(item.id)"
                        ng:on.blur="doSomething()">
                    X
                </button>
            </li>
    </div>
</ng:template>
@mhevery

This comment has been minimized.

Show comment
Hide comment
@mhevery

mhevery Mar 10, 2015

Member

I know this is a sensitive topic to a lot of you. We have gotten a lot of good feedback from this discussion which was incorporated into our thinking, and so I think this thread has served its purpose, and will now be retired.

Please watch my presentation on this topic: https://www.youtube.com/watch?v=-dMBcqwvYA0 which tries to answer many of the questions.

Member

mhevery commented Mar 10, 2015

I know this is a sensitive topic to a lot of you. We have gotten a lot of good feedback from this discussion which was incorporated into our thinking, and so I think this thread has served its purpose, and will now be retired.

Please watch my presentation on this topic: https://www.youtube.com/watch?v=-dMBcqwvYA0 which tries to answer many of the questions.

@lukehutch

This comment has been minimized.

Show comment
Hide comment
@lukehutch

lukehutch Jun 30, 2015

I'm late to the party here, but what about simply treating property binding as an event?:

<web-component [title]="exp1" (close)="exp2()">

would be

<web-component ng-on-bind="ngBind('title',exp1)" ng-on-close="exp2()">

where "ng-on-" would be a reserved prefix.

(As a bonus, it might actually be useful to be able to execute an arbitrary expression at bind time.)

lukehutch commented Jun 30, 2015

I'm late to the party here, but what about simply treating property binding as an event?:

<web-component [title]="exp1" (close)="exp2()">

would be

<web-component ng-on-bind="ngBind('title',exp1)" ng-on-close="exp2()">

where "ng-on-" would be a reserved prefix.

(As a bonus, it might actually be useful to be able to execute an arbitrary expression at bind time.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment