Skip to content

Commit 6f77063

Browse files
authored
Merge pull request #1924 from ember-learn/plain-function-helpers
Update helper guides to use regular functions
2 parents 77c2199 + 60626b2 commit 6f77063

File tree

1 file changed

+47
-31
lines changed

1 file changed

+47
-31
lines changed

guides/release/components/helper-functions.md

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -184,32 +184,12 @@ Next to local helpers, ember provides a way to use global helpers. We define glo
184184
</div>
185185
</div>
186186

187-
To implement the helper, we write a JavaScript function that takes its arguments as an _array_. This is because helpers can also receive _named_
188-
arguments, which we'll discuss next.
187+
To implement the helper, we define and export a regular JavaScript function:
189188

190189
```js {data-filename="app/helpers/substring.js"}
191-
import { helper } from '@ember/component/helper';
192-
193-
function substring(args) {
194-
let [string, start, end] = args;
195-
return string.substring(start, end);
196-
}
197-
198-
export default helper(substring);
199-
```
200-
201-
We can tighten up the implementation by moving the [destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) into the function's signature.
202-
203-
```js {data-filename="app/helpers/substring.js" data-diff="+3,-4,-5"}
204-
import { helper } from '@ember/component/helper';
205-
206-
function substring([string, start, end]) {
207-
function substring(args) {
208-
let [string, start, end] = args;
190+
export default function substring(string, start, end) {
209191
return string.substring(start, end);
210192
}
211-
212-
export default helper(substring);
213193
```
214194

215195
We can then use this helper in the component's template to get the first letter of the username.
@@ -255,36 +235,72 @@ Similar to local helpers, global helpers also can mix positional and named argum
255235
</section>
256236
```
257237

238+
```js {data-filename="app/helpers/substring.js"}
239+
export default function substring(string, { start, end }) {
240+
return string.substring(start || 0, end);
241+
}
242+
```
243+
244+
### Classic Helpers
245+
246+
Sometimes, you may encounter helpers defined using the `helper` function:
247+
258248
```js {data-filename="app/helpers/substring.js"}
259249
import { helper } from '@ember/component/helper';
260250

261-
function substring([string], { start, end }) {
251+
function substring(positional, { start, end }) {
252+
const string = positional[0];
262253
return string.substring(start || 0, end);
263254
}
264255

265256
export default helper(substring);
266257
```
267258

259+
<div class="cta">
260+
<div class="cta-note">
261+
<div class="cta-note-body">
262+
<div class="cta-note-heading">Zoey says...</div>
263+
<div class="cta-note-message">
264+
Before Ember 4.5, this was the only way to define helpers.
265+
</div>
266+
</div>
267+
<img src="/images/mascots/zoey.png" role="presentation" alt="">
268+
</div>
269+
</div>
270+
271+
By wrapping the function using the `helper()` function, Ember will extract the
272+
arguments passed from the template. It'll then call your function with an array
273+
(positional arguments passed in the template) and an object (named arguments
274+
passed in the template).
275+
276+
This style mostly exists for backwards compatibility reasons, but the other
277+
advantage is that it makes it easier to untangle the positional and named
278+
arguments (e.g. when your helper accept an arbitrary number of positional
279+
arguments and optionally some named arguments). Note that, however, it also
280+
makes it more difficult to reuse the logic of the helper function from regular
281+
JavaScript code outside of templates. On the other hand, if you define your
282+
helpers as plain JavaScript function, as we have been doing until now, you are
283+
able to import and call them from any JavaScript files in your app.
284+
268285
### Class Helpers
269286

270-
Helpers can also be defined using class syntax. For instance, we could define
271-
the substring helper using classes instead.
287+
Classic helpers can also be defined using class syntax. For instance, we could
288+
define the substring helper using classes instead.
272289

273-
```js {data-filename="app/helpers/substring.js" data-diff="-1,+2,-4,+5,+6,+8"}
274-
import { helper } from '@ember/component/helper';
290+
```js {data-filename="app/helpers/substring.js"}
275291
import Helper from '@ember/component/helper';
276292

277-
function substring([string], { start, length }) {
278293
export default class Substring extends Helper {
279-
compute([string], { start, end }) {
294+
compute(positional, { start, end }) {
295+
const string = positional[0];
280296
return string.substring(start || 0, end);
281297
}
282298
}
283299
```
284300

285301
Class helpers are useful when the helper logic is fairly complicated, requires
286-
fine-grained control of the helper lifecycle, or is _stateful_ (we'll be
287-
discussing state in the next chapter).
302+
fine-grained control of the helper lifecycle, is _stateful_ (we'll be
303+
discussing state in the next chapter), or requiring access to a [service](../../services/).
288304

289305
## Built-in Helpers
290306

0 commit comments

Comments
 (0)