@@ -9,11 +9,7 @@ When Ember first renders a component, it renders the initial _state_ of that
99component - the state of the instance, and state of the arguments that are
1010passed to it:
1111
12- ``` handlebars {data-filename=app/components/hello.hbs}
13- {{this.greeting}}, {{@name}}!
14- ```
15-
16- ``` js {data-filename=app/components/hello.js}
12+ ``` gjs {data-filename=app/components/hello.gjs}
1713import Component from '@glimmer/component';
1814
1915export default class HelloComponent extends Component {
@@ -29,11 +25,19 @@ export default class HelloComponent extends Component {
2925 return 'Hola';
3026 }
3127 }
28+
29+ <template>
30+ {{this.greeting}}, {{@name}}!
31+ </template>
3232}
3333```
3434
35- ``` handlebars {data-filename=app/templates/application.hbs}
36- <Hello @name="Jen Weber">
35+ ``` gjs {data-filename=app/templates/application.gjs}
36+ import 'my-app/components/hello';
37+
38+ <template>
39+ <Hello @name="Jen Weber">
40+ </template>
3741```
3842
3943When Ember renders this template, we get:
@@ -59,11 +63,12 @@ Trackable values are values that:
5963
6064We can do this by marking the field with the ` @tracked ` decorator:
6165
62- ``` js {data-filename=app/components/hello.js }
66+ ``` gjs {data-filename=app/components/hello.gjs data-diff="+2,-5,+6" }
6367import Component from '@glimmer/component';
6468import { tracked } from '@glimmer/tracking';
6569
6670export default class HelloComponent extends Component {
71+ language = 'en';
6772 @tracked language = 'en';
6873
6974 get greeting() {
@@ -76,6 +81,10 @@ export default class HelloComponent extends Component {
7681 return 'Hola';
7782 }
7883 }
84+
85+ <template>
86+ {{this.greeting}}, {{@name}}!
87+ </template>
7988}
8089```
8190
@@ -95,20 +104,10 @@ Tracked properties can be updated like any other property, using standard
95104JavaScript syntax. For instance, we could update a tracked property via an
96105action, as in this example component.
97106
98- ``` handlebars {data-filename=app/components/hello.hbs}
99- {{this.greeting}}, {{@name}}!
100-
101- <select {{on "change" this.updateLanguage}}>
102- <option value="en">English</option>
103- <option value="de">German</option>
104- <option value="sp">Spanish</option>
105- </select>
106- ```
107-
108- ``` js {data-filename=app/components/hello.js}
107+ ``` gjs { data-filename=app/components/hello.gjs data-diff="+3,+18,+19,+20,+21,+25,+26,+27,+28,+29,+30" }
109108import Component from '@glimmer/component';
110109import { tracked } from '@glimmer/tracking';
111- import { action } from ' @ember/object ' ;
110+ import { on } from '@ember/modifier ';
112111
113112export default class HelloComponent extends Component {
114113 @tracked language = 'en';
@@ -124,10 +123,19 @@ export default class HelloComponent extends Component {
124123 }
125124 }
126125
127- @action
128- updateLanguage (event ) {
126+ updateLanguage = (event) => {
129127 this.language = event.target.value;
130- }
128+ };
129+
130+ <template>
131+ {{this.greeting}}, {{@name}}!
132+
133+ <select {{on "change" this.updateLanguage}}>
134+ <option value="en">English</option>
135+ <option value="de">German</option>
136+ <option value="sp">Spanish</option>
137+ </select>
138+ </template>
131139}
132140```
133141
@@ -140,10 +148,10 @@ Another way that a tracked property could be updated is asynchronously, if
140148you're sending a request to the server. For instance, maybe we would want to
141149load the user's preferred language:
142150
143- ``` js
151+ ``` gjs { data-filename=app/components/hello.gjs data-diff="+6,+7,+8,+9,+10,+11,+12,+13,+14,+15" }
144152import Component from '@glimmer/component';
145153import { tracked } from '@glimmer/tracking';
146- import { action } from ' @ember/object ' ;
154+ import { on } from '@ember/modifier ';
147155
148156export default class HelloComponent extends Component {
149157 constructor() {
@@ -168,6 +176,20 @@ export default class HelloComponent extends Component {
168176 return 'Hola';
169177 }
170178 }
179+
180+ updateLanguage = (event) => {
181+ this.language = event.target.value;
182+ };
183+
184+ <template>
185+ {{this.greeting}}, {{@name}}!
186+
187+ <select {{on "change" this.updateLanguage}}>
188+ <option value="en">English</option>
189+ <option value="de">German</option>
190+ <option value="sp">Spanish</option>
191+ </select>
192+ </template>
171193}
172194```
173195
@@ -180,16 +202,26 @@ app.
180202So far we've only shown tracked properties working through getters, but tracking
181203works through _ methods_ or _ functions_ as well:
182204
183- ``` js
205+ ``` gjs { data-diff="+17,+18,+19,+20,+21,+24,+25,+26,+27" }
184206import Component from '@glimmer/component';
185207import { tracked } from '@glimmer/tracking';
186- import { action } from ' @ember/object ' ;
208+ import { on } from '@ember/modifier ';
187209
188210export default class HelloComponent extends Component {
211+ constructor() {
212+ super(...arguments);
213+
214+ fetch('/api/preferences')
215+ .then(r => r.json()) // convert the response to a JS object
216+ .then(response => {
217+ this.language = response.preferredLanguage;
218+ });
219+ }
220+
189221 @tracked language = 'en';
190222 @tracked supportedLanguages = ['en', 'de', 'es'];
191223
192- isSupported (language ) {
224+ isSupported = (language) => {
193225 return this.supportedLanguages.includes(language);
194226 }
195227
@@ -207,6 +239,20 @@ export default class HelloComponent extends Component {
207239 return 'Hola';
208240 }
209241 }
242+
243+ updateLanguage = (event) => {
244+ this.language = event.target.value;
245+ };
246+
247+ <template>
248+ {{this.greeting}}, {{@name}}!
249+
250+ <select {{on "change" this.updateLanguage}}>
251+ <option value="en">English</option>
252+ <option value="de">German</option>
253+ <option value="sp">Spanish</option>
254+ </select>
255+ </template>
210256}
211257```
212258
@@ -237,7 +283,7 @@ export default class Person {
237283
238284``` js {data-filename=app/routes/application.js}
239285import Route from ' @ember/routing/route' ;
240- import Person from ' ../../../.. /utils/person' ;
286+ import Person from ' my-app /utils/person' ;
241287
242288export default class ApplicationRoute extends Route {
243289 model () {
@@ -246,27 +292,27 @@ export default class ApplicationRoute extends Route {
246292}
247293```
248294
249- ``` js {data-filename=app/controllers/application.js}
250- import Controller from ' @ember/controller' ;
251- import { action } from ' @ember/object' ;
252-
253- export default class ApplicationController extends Controller {
254- @action
255- updateName (title , name ) {
256- this .model .title = title;
257- this .model .name = name;
258- }
295+ ``` gjs {data-filename=app/templates/application.gjs}
296+ import Component from '@glimmer/component';
297+ import { on } from '@ember/modifier';
298+ import { fn } from '@ember/helper';
299+
300+ export default class ApplicationRouteComponent extends Component {
301+ updateName = (title, name) => {
302+ this.args.model.title = title;
303+ this.args.model.name = name;
304+ };
305+
306+ <template>
307+ {{@model.fullName}}
308+
309+ <button type="button" {{on "click" (fn this.updateName 'Prof.' 'Tomster')}}>
310+ Update Name
311+ </button>
312+ </template>
259313}
260314```
261315
262- ``` handlebars {data-filename=app/templates/application.hbs}
263- {{@model.fullName}}
264-
265- <button type="button" {{on "click" (fn this.updateName 'Prof.' 'Tomster')}}>
266- Update Name
267- </button>
268- ```
269-
270316As long as the properties are tracked, and accessed when rendering the template
271317directly or indirectly, everything should update as expected
272318
@@ -362,7 +408,8 @@ you cache (or "memoize") a getter by simply marking it as `@cached`.
362408
363409With this in mind, let's introduce caching to ` aspectRatio ` :
364410
365- ``` js
411+ ``` js { data-diff="-1,+2,+10,-22,+23,-28,+29" }
412+ import { tracked } from ' @glimmer/tracking' ;
366413import { cached , tracked } from ' @glimmer/tracking' ;
367414
368415let count = 0 ;
@@ -383,11 +430,13 @@ let photo = new Photo();
383430console .log (photo .aspectRatio ); // 1.5
384431console .log (count); // 1
385432console .log (photo .aspectRatio ); // 1.5
433+ console .log (count); // 2
386434console .log (count); // 1
387435
388436photo .width = 800 ;
389437
390438console .log (photo .aspectRatio ); // 2
439+ console .log (count); // 3
391440console .log (count); // 2
392441```
393442
0 commit comments