Skip to content

Commit a679ce0

Browse files
committed
Writing template-tag version of "Responding to user interactions"
1 parent f8f9d02 commit a679ce0

File tree

1 file changed

+112
-4
lines changed

1 file changed

+112
-4
lines changed

guides/release/getting-started/quick-start.md

Lines changed: 112 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -397,16 +397,17 @@ The only difference is that now we've componentized our list into a version that
397397
You can see this in action if you create a new route that shows a different list of people.
398398
As an additional exercise (that we won't cover),
399399
you can try to create a `programmers` route that shows a list of famous programmers.
400-
If you re-use the `<PeopleList>` component, you can do it with almost no code at all.
400+
If you re-use the `PeopleList` component, you can do it with almost no code at all.
401401

402402
## Responding to user interactions
403403

404404
So far, our application is listing data, but there is no way for the user to
405405
interact with the information. In web applications we often want to respond to
406406
user actions like clicks or hovers. Ember makes this easy to do.
407407

408-
First, we can modify the `<PeopleList>` component to include a button:
408+
First, we can modify the `PeopleList` component to include a button:
409409

410+
<feature-flag-off-template-tag>
410411
```handlebars {data-filename="app/components/people-list.hbs"}
411412
<h2>{{@title}}</h2>
412413
@@ -418,16 +419,34 @@ First, we can modify the `<PeopleList>` component to include a button:
418419
{{/each}}
419420
</ul>
420421
```
422+
</feature-flag-off-template-tag>
423+
<feature-flag-on-template-tag>
424+
```gjs {data-filename="app/components/people-list.gjs"}
425+
<template>
426+
<h2>{{@title}}</h2>
427+
428+
<ul>
429+
{{#each @people as |person|}}
430+
<li>
431+
<button type="button">{{person}}</button>
432+
</li>
433+
{{/each}}
434+
</ul>
435+
</template>
436+
```
437+
</feature-flag-on-template-tag>
438+
421439

422440
Now that we have a button, we need to wire it up to do _something_ when a user
423441
clicks on it. For simplicity, let's say we want to show an `alert` dialog with
424442
the person's name when the button is clicked.
425443

426-
So far, our `<PeopleList>` component is purely presentational – it takes some
444+
So far, our `PeopleList` component is purely presentational – it takes some
427445
inputs as arguments and renders them using a template. To introduce _behavior_
428446
to our component – handling the button click in this case, we will need to
429-
attach some _code_ to the component.
447+
attach some JavaScript to the component.
430448

449+
<feature-flag-off-template-tag>
431450
In addition to the template, a component can also have a JavaScript file for
432451
this exact purpose. Go ahead and create a `.js` file with the same name and in
433452
the same directory as our template (`app/components/people-list.js`),
@@ -496,6 +515,95 @@ helper to pass the `person` as an argument which our action expects.
496515

497516
Feel free to try this in the browser. Finally, everything should behave exactly
498517
as we hoped!
518+
</feature-flag-off-template-tag>
519+
520+
<feature-flag-on-template-tag>
521+
522+
Let's use the [`on` modifier](../../components/template-lifecycle-dom-and-modifiers/#toc_event-handlers) to handle click events on the button:
523+
524+
```gjs {data-filename="app/components/people-list.gjs"}
525+
import { on } from '@ember/modifier'
526+
527+
function showPerson(clickEvent) {
528+
alert(`You clicked on a button labeled ${clickEvent.target.innerHTML}`);
529+
}
530+
531+
<template>
532+
<h2>{{@title}}</h2>
533+
534+
<ul>
535+
{{#each @people as |person|}}
536+
<li>
537+
<button type="button" {{on "click" showPerson}}>{{person}}</button>
538+
</li>
539+
{{/each}}
540+
</ul>
541+
</template>
542+
```
543+
544+
Now let's extend our example to pass the Person to our event handler as an argument. We can use the [`fn` helper](../../components/component-state-and-actions/#toc_passing-arguments-to-actions):
545+
546+
```gjs {data-filename="app/components/people-list.gjs"}
547+
import { on } from '@ember/modifier'
548+
import { fn } from '@ember/helper';
549+
550+
function showPerson(person) {
551+
alert(`You clicked on ${person}`);
552+
}
553+
554+
<template>
555+
<h2>{{@title}}</h2>
556+
557+
<ul>
558+
{{#each @people as |person|}}
559+
<li>
560+
<button type="button" {{on "click" (fn showPerson person) }}>{{person}}</button>
561+
</li>
562+
{{/each}}
563+
</ul>
564+
</template>
565+
```
566+
567+
Many components will need to maintain some state. Let's introduce a `currentPerson` that keeps track of which Person the user clicked on last. The idiomatic way to keep state in an Ember component is to use [`@tracked`](../../in-depth-topics/autotracking-in-depth/) on a component class:
568+
569+
```gjs {data-filename="app/components/people-list.gjs"}
570+
import { on } from '@ember/modifier'
571+
import { fn } from '@ember/helper';
572+
import { tracked } from '@glimmer/tracking';
573+
import Component from '@glimmer/component';
574+
575+
export default class extends Component {
576+
@tracked currentPerson;
577+
578+
showPerson = (person) => {
579+
this.currentPerson = person;
580+
};
581+
582+
isCurrentPerson = (person) => {
583+
return this.currentPerson === person;
584+
};
585+
586+
<template>
587+
<h2>{{@title}}</h2>
588+
589+
<ul>
590+
{{#each @people as |person|}}
591+
<li>
592+
<button type="button" {{on "click" (fn this.showPerson person) }}>{{person}}</button>
593+
{{#if (this.isCurrentPerson person) }}
594+
⬅️
595+
{{/if}}
596+
</li>
597+
{{/each}}
598+
</ul>
599+
</template>
600+
}
601+
```
602+
603+
</feature-flag-on-template-tag>
604+
605+
606+
499607

500608
## Building For Production
501609

0 commit comments

Comments
 (0)