Skip to content

Commit f971719

Browse files
authored
Merge pull request #20728 from emberjs/cleanup-action-modifier
2 parents 85fa73f + 9cb8cf5 commit f971719

File tree

7 files changed

+48
-156
lines changed

7 files changed

+48
-156
lines changed

packages/@ember/-internals/glimmer/lib/component.ts

Lines changed: 33 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,8 @@ declare const SIGNATURE: unique symbol;
205205
default for older editions of Ember (pre 3.15).
206206
207207
Below is the documentation for Classic components. If you are looking for the
208-
API documentation for Template-only or Glimmer components, it is
209-
[available here](/ember/release/modules/@glimmer%2Fcomponent).
208+
API documentation for Template-only or Glimmer components, it is [available
209+
here](/ember/release/modules/@glimmer%2Fcomponent).
210210
211211
## Defining a Classic Component
212212
@@ -404,9 +404,9 @@ declare const SIGNATURE: unique symbol;
404404
<div id="ember1" class="ember-view empty"></div>
405405
```
406406
407-
If you want to add a class name for a property which evaluates to true and
408-
and a different class name if it evaluates to false, you can pass a binding
409-
like this:
407+
If you want to add a class name for a property which evaluates to true and and
408+
a different class name if it evaluates to false, you can pass a binding like
409+
this:
410410
411411
```app/components/my-widget.js
412412
import Component from '@ember/component';
@@ -467,9 +467,9 @@ declare const SIGNATURE: unique symbol;
467467
### Other HTML Attributes
468468
469469
The HTML attribute section of a component's tag can be set by providing an
470-
`attributeBindings` property set to an array of property names on the component.
471-
The return value of these properties will be used as the value of the component's
472-
HTML associated attribute:
470+
`attributeBindings` property set to an array of property names on the
471+
component. The return value of these properties will be used as the value of
472+
the component's HTML associated attribute:
473473
474474
```app/components/my-anchor.js
475475
import Component from '@ember/component';
@@ -488,8 +488,8 @@ declare const SIGNATURE: unique symbol;
488488
<a id="ember1" class="ember-view" href="http://google.com"></a>
489489
```
490490
491-
One property can be mapped on to another by placing a ":" between
492-
the source property and the destination property:
491+
One property can be mapped on to another by placing a ":" between the source
492+
property and the destination property:
493493
494494
```app/components/my-anchor.js
495495
import Component from '@ember/component';
@@ -522,9 +522,9 @@ declare const SIGNATURE: unique symbol;
522522
<a id="ember1" class="ember-view" href="http://bing.com"></a>
523523
```
524524
525-
Note that the `href` attribute is ultimately set to `http://bing.com`,
526-
despite it having attribute binidng to the `url` property, which was
527-
set to `http://google.com`.
525+
Note that the `href` attribute is ultimately set to `http://bing.com`, despite
526+
it having attribute binidng to the `url` property, which was set to
527+
`http://google.com`.
528528
529529
Namespaced attributes (e.g. `xlink:href`) are supported, but have to be
530530
mapped, since `:` is not a valid character for properties in Javascript:
@@ -662,27 +662,33 @@ declare const SIGNATURE: unique symbol;
662662
663663
## Handling Browser Events
664664
665-
Components can respond to user-initiated events in one of three ways: passing
666-
actions with angle bracket invocation, adding event handler methods to the
667-
component's class, or adding actions to the component's template.
665+
There are two ways to handle user-initiated events:
668666
669-
### Passing Actions With Angle Bracket Invocation
667+
### Using the `on` modifier to capture browser events
670668
671-
For one-off events specific to particular instance of a component, it is possible
672-
to pass actions to the component's element using angle bracket invocation syntax.
669+
In a component's template, you can attach an event handler to any element with the `on` modifier:
673670
674671
```handlebars
675-
<MyWidget {{action 'firstWidgetClicked'}} />
676-
677-
<MyWidget {{action 'secondWidgetClicked'}} />
672+
<button {{on 'click' this.doSomething}} />
678673
```
679674
680-
In this case, when the first component is clicked on, Ember will invoke the
681-
`firstWidgetClicked` action. When the second component is clicked on, Ember
682-
will invoke the `secondWidgetClicked` action instead.
675+
This will call the function on your component:
676+
677+
```js
678+
import Component from '@ember/component';
679+
680+
export default class ExampleComponent extends Component {
681+
doSomething = (event) => {
682+
// `event` is the native click Event
683+
console.log('clicked on the button');
684+
};
685+
});
686+
```
683687
684-
Besides `{{action}}`, it is also possible to pass any arbitrary element modifiers
685-
using the angle bracket invocation syntax.
688+
See the [Guide on Component event
689+
handlers](https://guides.emberjs.com/release/components/component-state-and-actions/#toc_html-modifiers-and-actions)
690+
and the [API docs for `on`](../Ember.Templates.helpers/methods/on?anchor=on)
691+
for more details.
686692
687693
### Event Handler Methods
688694
@@ -752,43 +758,6 @@ declare const SIGNATURE: unique symbol;
752758
* `dragEnd`
753759
* `drop`
754760
755-
### `{{action}}` Helper
756-
757-
Instead of handling all events of a particular type anywhere inside the
758-
component's element, you may instead want to limit it to a particular
759-
element in the component's template. In this case, it would be more
760-
convenient to implement an action instead.
761-
762-
For example, you could implement the action `hello` for the `person-profile`
763-
component:
764-
765-
```app/components/person-profile.js
766-
import Component from '@ember/component';
767-
768-
export default Component.extend({
769-
actions: {
770-
hello(name) {
771-
console.log("Hello", name);
772-
}
773-
}
774-
});
775-
```
776-
777-
And then use it in the component's template:
778-
779-
```app/templates/components/person-profile.hbs
780-
<h1>{{@person.name}}</h1>
781-
782-
<button {{action 'hello' @person.name}}>
783-
Say Hello to {{@person.name}}
784-
</button>
785-
```
786-
787-
When the user clicks the button, Ember will invoke the `hello` action,
788-
passing in the current value of `@person.name` as an argument.
789-
790-
See [Ember.Templates.helpers.action](/ember/release/classes/Ember.Templates.helpers/methods/action?anchor=action).
791-
792761
@class Component
793762
@extends Ember.CoreView
794763
@uses Ember.TargetActionSupport

packages/@ember/-internals/glimmer/lib/helpers/action.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ export const ACTIONS = new WeakSet();
275275
```
276276
277277
@method action
278+
@deprecated
278279
@for Ember.Templates.helpers
279280
@public
280281
*/

packages/@ember/component/template-only.ts

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,32 +34,9 @@ import { type Opaque } from '@ember/-internals/utility-types';
3434
import { templateOnlyComponent as glimmerTemplateOnlyComponent } from '@glimmer/runtime';
3535

3636
/**
37-
* Template-only components have no backing class instance, so this in their
37+
* Template-only components have no backing class instance, so `this` in their
3838
* templates is null. This means that you can only reference passed in arguments
39-
* via named argument syntax (e.g. `{{@arg}}`):
40-
*
41-
* ```hbs
42-
* {{!--
43-
* This does not work, since `this` does not exist
44-
* --}}
45-
* <label for="title">Title</label>
46-
* <Input @value={{this.value}} id="title" />
47-
* ```
48-
*
49-
* Additionally, the mut helper generally can't be used for the same reason:
50-
*
51-
* ```hbs
52-
* {{!-- This does not work --}}
53-
* <input
54-
* value={{this.value}}
55-
* onkeyup={{action (mut this.value) target="value"}}
56-
* />
57-
* ```
58-
*
59-
* Since Octane, a template-only component shares a subset of features that are
60-
* available in `@glimmer/component`. Such component can be seamlessly
61-
* "upgraded" to a Glimmer component, when you add a JavaScript file alongside
62-
* the template.
39+
* (e.g. `{{@arg}}`).
6340
*/
6441
// eslint-disable-next-line @typescript-eslint/no-empty-interface
6542
export interface TemplateOnlyComponent<S = unknown> extends Opaque<S> {}

packages/@ember/object/index.ts

Lines changed: 11 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -54,31 +54,21 @@ export default EmberObject;
5454
5555
```js
5656
import Component from '@ember/component';
57-
import { action, set } from '@ember/object';
57+
import { tracked } from '@glimmer/tracking';
58+
import { action } from '@ember/object';
5859
5960
export default class Tooltip extends Component {
61+
@tracked isShowing = false;
62+
6063
@action
6164
toggleShowing() {
62-
set(this, 'isShowing', !this.isShowing);
65+
this.isShowing = !this.isShowing;
6366
}
6467
}
6568
```
6669
```hbs
6770
<!-- template.hbs -->
68-
<button {{action this.toggleShowing}}>Show tooltip</button>
69-
70-
{{#if isShowing}}
71-
<div class="tooltip">
72-
I'm a tooltip!
73-
</div>
74-
{{/if}}
75-
```
76-
77-
Decorated actions also interop with the string style template actions:
78-
79-
```hbs
80-
<!-- template.hbs -->
81-
<button {{action "toggleShowing"}}>Show tooltip</button>
71+
<button {{on "click" this.toggleShowing}}>Show tooltip</button>
8272
8373
{{#if isShowing}}
8474
<div class="tooltip">
@@ -90,27 +80,10 @@ export default EmberObject;
9080
It also binds the function directly to the instance, so it can be used in any
9181
context and will correctly refer to the class it came from:
9282
93-
```hbs
94-
<!-- template.hbs -->
95-
<button
96-
{{did-insert this.toggleShowing}}
97-
{{on "click" this.toggleShowing}}
98-
>
99-
Show tooltip
100-
</button>
101-
102-
{{#if isShowing}}
103-
<div class="tooltip">
104-
I'm a tooltip!
105-
</div>
106-
{{/if}}
107-
```
108-
109-
This can also be used in JavaScript code directly:
110-
11183
```js
11284
import Component from '@ember/component';
113-
import { action, set } from '@ember/object';
85+
import { tracked } from '@glimmer/tracking';
86+
import { action } from '@ember/object';
11487
11588
export default class Tooltip extends Component {
11689
constructor() {
@@ -121,37 +94,15 @@ export default EmberObject;
12194
document.addEventListener('click', this.toggleShowing);
12295
}
12396
97+
@tracked isShowing = false;
98+
12499
@action
125100
toggleShowing() {
126-
set(this, 'isShowing', !this.isShowing);
101+
this.isShowing = !this.isShowing;
127102
}
128103
}
129104
```
130105
131-
This is considered best practice, since it means that methods will be bound
132-
correctly no matter where they are used. By contrast, the `{{action}}` helper
133-
and modifier can also be used to bind context, but it will be required for
134-
every usage of the method:
135-
136-
```hbs
137-
<!-- template.hbs -->
138-
<button
139-
{{did-insert (action this.toggleShowing)}}
140-
{{on "click" (action this.toggleShowing)}}
141-
>
142-
Show tooltip
143-
</button>
144-
145-
{{#if isShowing}}
146-
<div class="tooltip">
147-
I'm a tooltip!
148-
</div>
149-
{{/if}}
150-
```
151-
152-
They also do not have equivalents in JavaScript directly, so they cannot be
153-
used for other situations where binding would be useful.
154-
155106
@public
156107
@method action
157108
@for @ember/object

packages/@ember/routing/hash-location.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,6 @@ export default class HashLocation extends EmberObject implements EmberLocation {
146146
Given a URL, formats it to be placed into the page as part
147147
of an element's `href` attribute.
148148
149-
This is used, for example, when using the {{action}} helper
150-
to generate a URL based on an event.
151-
152149
@private
153150
@method formatURL
154151
@param url {String}

packages/@ember/routing/history-location.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ export default class HistoryLocation extends EmberObject implements EmberLocatio
246246
}
247247

248248
/**
249-
Used when using `{{action}}` helper. The url is always appended to the rootURL.
249+
Formats url to be placed into href attribute.
250250
251251
@private
252252
@method formatURL

packages/@ember/routing/none-location.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,6 @@ export default class NoneLocation extends EmberObject implements EmberLocation {
110110
Given a URL, formats it to be placed into the page as part
111111
of an element's `href` attribute.
112112
113-
This is used, for example, when using the {{action}} helper
114-
to generate a URL based on an event.
115-
116113
@private
117114
@method formatURL
118115
@param {String} url

0 commit comments

Comments
 (0)