From dc685e1a29bf7a9f533a8a4b3b37de4a39860000 Mon Sep 17 00:00:00 2001 From: Matthew Beale Date: Wed, 19 Jul 2023 09:54:27 -0400 Subject: [PATCH 1/2] Update the guides for element modifiers At https://github.com/emberjs/rfcs/pull/934 we're tracking an effort to implement the RFC https://github.com/emberjs/rfcs/pull/811. In that RFC (at https://github.com/emberjs/rfcs/blob/master/text/0811-element-modifiers.md#how-we-teach-this) there are two things which are suggested for documentation in the guides: * Update references that mention `ember-modifier` must be installed, since it ships in the default blueprint (confirmed at https://github.com/ember-cli/ember-new-output/blob/master/package.json#L50) * Introduce the class-based modifier API. In this PR I've linked to the upstream documentation at https://github.com/ember-modifier/ember-modifier#usage to execute on that suggestion. I don't believe we need to laborously explain the class-based APIs to guides readers, it just distracts from some otherwise straight-forward use cases and examples. --- .../template-lifecycle-dom-and-modifiers.md | 22 +++++++----- .../current-edition/glimmer-components.md | 34 +++++++++++-------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/guides/release/components/template-lifecycle-dom-and-modifiers.md b/guides/release/components/template-lifecycle-dom-and-modifiers.md index b8fb711cf4..13fa0e8c5c 100644 --- a/guides/release/components/template-lifecycle-dom-and-modifiers.md +++ b/guides/release/components/template-lifecycle-dom-and-modifiers.md @@ -293,10 +293,17 @@ The modifier that we're going to build will allow us to say: Pretty nice, right? -To accomplish that, we'll create a modifier in `app/modifiers/autofocus.js`. First, install [`ember-modifier`](https://github.com/ember-modifier/ember-modifier) and then generate an `autofocus` modifier for your app: +New Ember apps ship with a dependency on +[ember-modifier](https://github.com/ember-modifier/ember-modifier), which +provides a friendly API for writing your own element modifiers. This library is +in turn based on a low level API named _modifier managers_. Managers are a +framework-development level feature, and not something most developers need to +interact with. You'll see in the following examples that the modifier API is +imported from the `ember-modifier` package. + +First generate the `autofocus` modifier for your application: ```bash -ember install ember-modifier ember generate modifier autofocus ``` @@ -308,9 +315,10 @@ import { modifier } from "ember-modifier"; export default modifier(element => element.focus()); ``` -And that's it! +And that's it! Now we can use our custom `{{autofocus}}` modifier throughout our application. -Now we can use our custom `{{autofocus}}` modifier throughout our application. +Read more about the `ember-modifier` APIs at [ember-modifiers: +Usage](https://github.com/ember-modifier/ember-modifier#usage). ## Communicating Between Elements in a Component @@ -390,7 +398,6 @@ export default class AudioPlayerComponent extends Component { That's it for the component: we're translating the user's interactions into _state_. Now we need to build a modifier to translate the state into the appropriate DOM method calls! ```bash -ember install ember-modifier ember generate modifier play-when ``` @@ -448,12 +455,11 @@ document.addEventListener("click", event => { The most important difference between this example and the cases we've seen so far is that we need to remove the `click` event handler from the document when this element is destroyed. -To accomplish this, we can use [`ember-modifier`](https://github.com/ember-modifier/ember-modifier) to create a `on-click-outside` modifier that sets up the event listener after the element is first inserted and removes the event listener when the element is removed. +To accomplish this, we can use [`ember-modifier`](https://github.com/ember-modifier/ember-modifier) (which is already installed in newly generated Ember apps) to create a `on-click-outside` modifier that sets up the event listener after the element is first inserted and removes the event listener when the element is removed. -Run the following commands to install the addon and generate a new modifier: +Generate the new modifier: ```bash -ember install ember-modifier ember generate modifier on-click-outside ``` diff --git a/guides/release/upgrading/current-edition/glimmer-components.md b/guides/release/upgrading/current-edition/glimmer-components.md index c58b940104..af6db57ffb 100644 --- a/guides/release/upgrading/current-edition/glimmer-components.md +++ b/guides/release/upgrading/current-edition/glimmer-components.md @@ -784,15 +784,17 @@ functionality that lifecycle hooks contained. #### Writing your own modifiers -There are also community APIs available for writing your own modifiers, such as -[ember-modifier](https://github.com/ember-modifier/ember-modifier). -Ember itself has low level APIs known as _modifier managers_ which can be used -to write these higher level APIs. In general, it's recommended to use a -community addon to write modifiers, and _not_ to write your own modifier -manager. +New Ember apps ship with a dependency on +[ember-modifier](https://github.com/ember-modifier/ember-modifier), which +provides a friendly API for writing your own element modifiers. This library is +in turn based on a low level API named _modifier managers_. Managers are a +framework-development level feature, and not something most developers need to +interact with. -Let's see what our first example would look like if we were to write it as a -modifier using `ember-modifier`: +Custom modifiers based on the `ember-modifier` API can be a more expressive +interface for your logic, and can better encapsulate an implementation. + +Let's write a modifier that implements adding an event listener. ```js {data-filename=app/modifiers/add-event-listener.js} import { modifier } from 'ember-modifier'; @@ -825,12 +827,16 @@ export default class ScrollComponent extends Component { ``` -This modifier generalizes the functionality that the component implemented using -lifecycle hooks before, so we can use this modifier whenever we need to in _any_ -component. This is a much better solution than manually managing event listeners -every time we need one! At this point, the modifier is effectively the same as -the `{{on}}` modifier as well, so we could get rid of it altogether and replace -it with `on`: +The new `add-event-listener` modifier presents a more expressive interface to +the `hbs` template: There is only a single modifier to apply instead of two, the +implemention always tears down after itself upon teardown of the target element, +and the only JavaScript you have to write during re-user is the implementation +of the business logic. + +At this point, it is worth noting that the custom `{{add-event-listener}}` +modifier is effectively a re-implementation of the Ember built-in `{{on}}` +modifier (See the +[documentation](https://api.emberjs.com/ember/5.1/classes/Ember.Templates.helpers/methods/on?anchor=on)). Using that built-in looks like: ```handlebars {data-filename=app/components/scroll-component.hbs}
From 1031576c0a3b7882e7555a42d5a208f003d164a8 Mon Sep 17 00:00:00 2001 From: Matthew Beale Date: Fri, 11 Aug 2023 14:27:19 -0400 Subject: [PATCH 2/2] Update guides/release/upgrading/current-edition/glimmer-components.md --- guides/release/upgrading/current-edition/glimmer-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/release/upgrading/current-edition/glimmer-components.md b/guides/release/upgrading/current-edition/glimmer-components.md index af6db57ffb..b6781b926d 100644 --- a/guides/release/upgrading/current-edition/glimmer-components.md +++ b/guides/release/upgrading/current-edition/glimmer-components.md @@ -829,7 +829,7 @@ export default class ScrollComponent extends Component { The new `add-event-listener` modifier presents a more expressive interface to the `hbs` template: There is only a single modifier to apply instead of two, the -implemention always tears down after itself upon teardown of the target element, +implementation always tears down after itself upon teardown of the target element, and the only JavaScript you have to write during re-user is the implementation of the business logic.