Skip to content
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

Review and Octanify the template guides #598

Merged
merged 2 commits into from
Mar 14, 2019
Merged

Review and Octanify the template guides #598

merged 2 commits into from
Mar 14, 2019

Conversation

mixonic
Copy link
Contributor

@mixonic mixonic commented Mar 13, 2019

Copy link
Member

@acorncom acorncom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mixonic a few thoughts / comments, but thanks, that's much appreciated!

guides/release/templates/actions.md Outdated Show resolved Hide resolved
guides/release/templates/binding-element-attributes.md Outdated Show resolved Hide resolved
guides/release/templates/binding-element-attributes.md Outdated Show resolved Hide resolved
guides/release/templates/binding-element-attributes.md Outdated Show resolved Hide resolved
guides/release/templates/built-in-helpers.md Outdated Show resolved Hide resolved
guides/release/templates/writing-helpers.md Outdated Show resolved Hide resolved
guides/release/templates/writing-helpers.md Outdated Show resolved Hide resolved
guides/release/templates/writing-helpers.md Outdated Show resolved Hide resolved
}
}
```

## Modifying the action's first parameter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you remove this section because it ended up seeming confusing?

Copy link
Contributor Author

@mixonic mixonic Mar 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@acorncom excellent question! While editing these guide entries I was surprised to see onclick={{action this.foo}}-style actions being used widely. I brought it up vaguely in #st-octane and once my thoughts were more organized in #core-framework on Discord.

In Glimmer components there is no actions hash. Even with the @action decorator the following doesn't work:

import Component from '@glimmer/component';
import { action } from '@ember/object';

export default class extends Component {
  @action
  doThing() {
    // Do it!
  }
}
<button {{action 'doThing'}}>Do it!</button>

You cannot use a string to reference the action on the actions hash because there is no actions hash. And on glimmer component we see no need to create one. Note that a similar issue exists for native-class-Ember-component's which use the @action decorator and for native-class-syntax-controllers which do the same. They don't have an actions hash to reference with the string.

Instead, we intend to suggest developers reach for the @action-decorated property/method itself. For example:

import Component from '@glimmer/component';
import { action } from '@ember/object';

export default class extends Component {
  @action
  doThing() {
    // Do it!
  }
}
<button {{action this.doThing}}>Do it!</button>

But wait, I can just use onclick!

Clever developers will note that the above is using the action helper where it isn't strictly going to be needed. They might reach for the following:

{{!
  I know that @action binds the method to the component, so I'll just use
  use the bare method/action.
}}
<button onclick={{this.doThing}}>Do it!</button>

We would like to make this fail a linter check. Teaching that developers write an action this way has several downsides:

  • onclick= teaches that you can always attach an event listener with onfoo= syntax. This is not actually true. Some DOM elements trigger events (such as focusin) without calling the related property. Additionally web components don't call these properties. Instead you must attach an event listener. If developers learn this API first they will start off on the wrong foot.
  • onclick= works because Ember today has a "prop first, fallback to attribute" rule for how to set attributes on an element. Props can have subtle differences between attributes, even for the same values. More significantly properties have no way to be serialized into HTML, making them very difficult and in some cases impossible to pass to the browser when doing server-side rendering.
  • onclick= provides the developer no opportunity to pass arguments to the event listener. For example passive: true or capture: true. We should provide developers an API where opting into options for their listener is straightforward.
  • Finally we already have an API in <button {{action this.doThing}}> that does the work of onclick=. There are definitely ways to improve on the action modifier and helper, but onclick= doesn't offer much.

But it does offer me one thing: The event!

Correct! Using onclick= done one thing that the modifier {{action does not: It gives you access to the event. For example this calls the action alert with the value of the input every time it changes:

<input onchange={{action this.alert value="target.value"}}>

And this exact use of the API is what this subsection of the guide page is talking about. Although this behavior is not deprecated (and may be useful) we will not be suggesting onfoo= elsewhere for all the reasons outlined above, and so I do not think we should introduce this uncommon usage in the guides. It remains documented in the API docs

But I really don't like <button {{action this.foo}}>

Right. I agree it isn't all we want. For example you still can't add a listener for a custom event emitted by a web component to the action modifier. You can pass some useful arguments but not passive: true. You cannot get access to the event object.

Additionally some of the more advanced developers might know that the action modifier and helper have a special property: They bind an action passed to them to the context (or the value of the target= option if you pass one). They might think: "Ah ha you don't need the @action decorator!". But we do. We need the @action decorator to bind the actions onto the component so that in the future we can move from the action modifier (and maybe helper) to something better. We will provide a check that fails if you try to use {{action this.someProp}} and someProp has not had the @action decorator applied.

There is strong support among framework core that something akin to https://github.com/buschtoens/ember-on-modifier could become a built-in for Ember. The on modifier would solve most of the pain points around {{action. We cannot be sure it would ship in Octane at this late date, but we should consider soon how we can migrate existing action usage over to that new and better tool.

Final legacy note

Ember components and controllers with classic .extend({ should continue to use the action modifier or helper with the string argument. That class definition syntax does not have the ability to use the action decorator, and we see no need to churn code using that API with anything new.

guides/release/templates/writing-helpers.md Outdated Show resolved Hide resolved
guides/release/templates/writing-helpers.md Outdated Show resolved Hide resolved
* call them arguments (not parameters)
* use `positional` and `named`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants