@@ -397,16 +397,17 @@ The only difference is that now we've componentized our list into a version that
397397You can see this in action if you create a new route that shows a different list of people.
398398As an additional exercise (that we won't cover),
399399you 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
404404So far, our application is listing data, but there is no way for the user to
405405interact with the information. In web applications we often want to respond to
406406user 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
422440Now that we have a button, we need to wire it up to do _ something_ when a user
423441clicks on it. For simplicity, let's say we want to show an ` alert ` dialog with
424442the 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
427445inputs as arguments and renders them using a template. To introduce _ behavior_
428446to 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 >
431450In addition to the template, a component can also have a JavaScript file for
432451this exact purpose. Go ahead and create a ` .js ` file with the same name and in
433452the 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
497516Feel free to try this in the browser. Finally, everything should behave exactly
498517as 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