Skip to content

Convert in-depth topics to use gjs #2127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: gjs
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 96 additions & 47 deletions guides/release/in-depth-topics/autotracking-in-depth.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@ When Ember first renders a component, it renders the initial _state_ of that
component - the state of the instance, and state of the arguments that are
passed to it:

```handlebars {data-filename=app/components/hello.hbs}
{{this.greeting}}, {{@name}}!
```

```js {data-filename=app/components/hello.js}
```gjs {data-filename=app/components/hello.gjs}
import Component from '@glimmer/component';

export default class HelloComponent extends Component {
Expand All @@ -29,11 +25,19 @@ export default class HelloComponent extends Component {
return 'Hola';
}
}

<template>
{{this.greeting}}, {{@name}}!
</template>
}
```

```handlebars {data-filename=app/templates/application.hbs}
<Hello @name="Jen Weber">
```gjs {data-filename=app/templates/application.gjs}
import '../components/hello.gjs';

<template>
<Hello @name="Jen Weber">
</template>
```

When Ember renders this template, we get:
Expand All @@ -59,11 +63,12 @@ Trackable values are values that:

We can do this by marking the field with the `@tracked` decorator:

```js {data-filename=app/components/hello.js}
```gjs {data-filename=app/components/hello.gjs data-diff="+2,-5,+6"}
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

export default class HelloComponent extends Component {
language = 'en';
@tracked language = 'en';

get greeting() {
Expand All @@ -76,6 +81,10 @@ export default class HelloComponent extends Component {
return 'Hola';
}
}

<template>
{{this.greeting}}, {{@name}}!
</template>
}
```

Expand All @@ -95,20 +104,10 @@ Tracked properties can be updated like any other property, using standard
JavaScript syntax. For instance, we could update a tracked property via an
action, as in this example component.

```handlebars {data-filename=app/components/hello.hbs}
{{this.greeting}}, {{@name}}!

<select {{on "change" this.updateLanguage}}>
<option value="en">English</option>
<option value="de">German</option>
<option value="sp">Spanish</option>
</select>
```

```js {data-filename=app/components/hello.js}
``` gjs { data-filename=app/components/hello.gjs data-diff="+3,+18,+19,+20,+21,+25,+26,+27,+28,+29,+30" }
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { on } from '@ember/modifier';

export default class HelloComponent extends Component {
@tracked language = 'en';
Expand All @@ -124,10 +123,19 @@ export default class HelloComponent extends Component {
}
}

@action
updateLanguage(event) {
updateLanguage = (event) => {
this.language = event.target.value;
}
};

<template>
{{this.greeting}}, {{@name}}!

<select {{on "change" this.updateLanguage}}>
<option value="en">English</option>
<option value="de">German</option>
<option value="sp">Spanish</option>
</select>
</template>
}
```

Expand All @@ -140,10 +148,10 @@ Another way that a tracked property could be updated is asynchronously, if
you're sending a request to the server. For instance, maybe we would want to
load the user's preferred language:

```js
``` gjs { data-filename=app/components/hello.gjs data-diff="+6,+7,+8,+9,+10,+11,+12,+13,+14,+15" }
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { on } from '@ember/modifier';

export default class HelloComponent extends Component {
constructor() {
Expand All @@ -168,6 +176,20 @@ export default class HelloComponent extends Component {
return 'Hola';
}
}

updateLanguage = (event) => {
this.language = event.target.value;
};

<template>
{{this.greeting}}, {{@name}}!

<select {{on "change" this.updateLanguage}}>
<option value="en">English</option>
<option value="de">German</option>
<option value="sp">Spanish</option>
</select>
</template>
}
```

Expand All @@ -180,16 +202,26 @@ app.
So far we've only shown tracked properties working through getters, but tracking
works through _methods_ or _functions_ as well:

```js
``` gjs { data-diff="+17,+18,+19,+20,+21,+24,+25,+26,+27" }
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { on } from '@ember/modifier';

export default class HelloComponent extends Component {
constructor() {
super(...arguments);

fetch('/api/preferences')
.then(r => r.json()) // convert the response to a JS object
.then(response => {
this.language = response.preferredLanguage;
});
}

@tracked language = 'en';
@tracked supportedLanguages = ['en', 'de', 'es'];

isSupported(language) {
isSupported = (language) => {
return this.supportedLanguages.includes(language);
}

Expand All @@ -207,6 +239,20 @@ export default class HelloComponent extends Component {
return 'Hola';
}
}

updateLanguage = (event) => {
this.language = event.target.value;
};

<template>
{{this.greeting}}, {{@name}}!

<select {{on "change" this.updateLanguage}}>
<option value="en">English</option>
<option value="de">German</option>
<option value="sp">Spanish</option>
</select>
</template>
}
```

Expand Down Expand Up @@ -246,27 +292,27 @@ export default class ApplicationRoute extends Route {
}
```

```js {data-filename=app/controllers/application.js}
import Controller from '@ember/controller';
import { action } from '@ember/object';

export default class ApplicationController extends Controller {
@action
updateName(title, name) {
this.model.title = title;
this.model.name = name;
}
```gjs {data-filename=app/templates/application.gjs}
import Component from '@glimmer/component';
import { on } from '@ember/modifier';
import { fn } from '@ember/helper';

export default class ApplicationRouteComponent extends Component {
updateName = (title, name) => {
this.args.model.title = title;
this.args.model.name = name;
};

<template>
{{@model.fullName}}

<button type="button" {{on "click" (fn this.updateName 'Prof.' 'Tomster')}}>
Update Name
</button>
</template>
}
```

```handlebars {data-filename=app/templates/application.hbs}
{{@model.fullName}}

<button type="button" {{on "click" (fn this.updateName 'Prof.' 'Tomster')}}>
Update Name
</button>
```

As long as the properties are tracked, and accessed when rendering the template
directly or indirectly, everything should update as expected

Expand Down Expand Up @@ -362,7 +408,8 @@ you cache (or "memoize") a getter by simply marking it as `@cached`.

With this in mind, let's introduce caching to `aspectRatio`:

```js
``` js { data-diff="-1,+2,+10,-22,+23,-28,+29" }
import { tracked } from '@glimmer/tracking';
import { cached, tracked } from '@glimmer/tracking';

let count = 0;
Expand All @@ -383,11 +430,13 @@ let photo = new Photo();
console.log(photo.aspectRatio); // 1.5
console.log(count); // 1
console.log(photo.aspectRatio); // 1.5
console.log(count); // 2
console.log(count); // 1

photo.width = 800;

console.log(photo.aspectRatio); // 2
console.log(count); // 3
console.log(count); // 2
```

Expand Down
Loading