Skip to content

Commit f220607

Browse files
authored
Merge pull request #2118 from ember-learn/gjs-routing
Convert routing section to route components
2 parents 2a11756 + f3575c8 commit f220607

File tree

3 files changed

+136
-89
lines changed

3 files changed

+136
-89
lines changed

guides/release/routing/defining-your-routes.md

Lines changed: 79 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ To define a route, run
88
ember generate route route-name
99
```
1010

11-
This creates a route file at `app/routes/route-name.js`, a template for the route at `app/templates/route-name.hbs`,
11+
This creates a route file at `app/routes/route-name.js`, a template for the route at `app/templates/route-name.gjs`,
1212
and a unit test file at `tests/unit/routes/route-name-test.js`.
1313
It also adds the route to the router.
1414

@@ -42,15 +42,19 @@ Router.map(function() {
4242
Inside your templates, you can use [`<LinkTo />`](https://api.emberjs.com/ember/release/classes/Ember.Templates.components/methods/LinkTo?anchor=LinkTo) to navigate between
4343
routes, using the name that you provided to the `route` method.
4444

45-
```handlebars
46-
<LinkTo @route="index">
47-
<img class="logo">
48-
</LinkTo>
45+
```gjs
46+
import { LinkTo } from '@ember/routing';
4947
50-
<nav>
51-
<LinkTo @route="about">About</LinkTo>
52-
<LinkTo @route="favorites">Favorites</LinkTo>
53-
</nav>
48+
<template>
49+
<LinkTo @route="index">
50+
<img class="logo">
51+
</LinkTo>
52+
53+
<nav>
54+
<LinkTo @route="about">About</LinkTo>
55+
<LinkTo @route="favorites">Favorites</LinkTo>
56+
</nav>
57+
</template>
5458
```
5559

5660
The `<LinkTo />` component will also add an `active` class to the link that
@@ -65,7 +69,7 @@ Router.map(function() {
6569
```
6670

6771
The route defined above will by default use the `blog-post.js` route handler,
68-
the `blog-post.hbs` template, and be referred to as `blog-post` in any
72+
the `blog-post.gjs` template, and be referred to as `blog-post` in any
6973
`<LinkTo />` components.
7074

7175
Multi-word route names that break this convention, such as:
@@ -77,7 +81,7 @@ Router.map(function() {
7781
```
7882

7983
will still by default use the `blog-post.js` route handler and the
80-
`blog-post.hbs` template, but will be referred to as `blog_post` in any
84+
`blog-post.gjs` template, but will be referred to as `blog_post` in any
8185
`<LinkTo />` components.
8286

8387
## Nested Routes
@@ -109,17 +113,22 @@ ember generate route posts/new
109113
And then add the `{{outlet}}` helper to your template where you want the nested
110114
template to display. You can also add a page title with the current page name (using [page-title helper](../../accessibility/page-template-considerations/#toc_page-title)), this will help users with assistive technology know where they are in the website.
111115

112-
```handlebars {data-filename=templates/posts.hbs}
113-
{{page-title "Posts - Site Title"}}
114-
<h1>Posts</h1>
115-
{{!-- Display posts and other content --}}
116-
{{outlet}}
116+
```gjs {data-filename=templates/posts.gjs}
117+
import { pageTitle } from 'ember-page-title'
118+
119+
<template>
120+
{{pageTitle "Posts - Site Title"}}
121+
122+
<h1>Posts</h1>
123+
{{!-- Display posts and other content --}}
124+
{{outlet}}
125+
</template>
117126
```
118127

119128
This generates a route for `/posts` and for `/posts/new`. When a user
120-
visits `/posts`, they'll simply see the `posts.hbs` template. (Below, [index
129+
visits `/posts`, they'll simply see the `posts.gjs` template. (Below, [index
121130
routes](#toc_index-routes) explains an important addition to this.) When the
122-
user visits `posts/new`, they'll see the `posts/new.hbs` template rendered into
131+
user visits `posts/new`, they'll see the `posts/new.gjs` template rendered into
123132
the `{{outlet}}` of the `posts` template.
124133

125134
A nested route name includes the names of its ancestors.
@@ -134,7 +143,7 @@ routes, it will load a template with the same name (`application` in
134143
this case) by default.
135144
You should put your header, footer, and any other decorative content
136145
here. All other routes will render
137-
their templates into the `application.hbs` template's `{{outlet}}`.
146+
their templates into the `application.gjs` template's `{{outlet}}`.
138147

139148
This route is part of every application, so you don't need to
140149
specify it in your `app/router.js`.
@@ -200,38 +209,51 @@ replace the `{{outlet}}` in the `posts` template with the
200209

201210
The following scenarios may help with understanding the `index` route:
202211

203-
- The top-level index route is analogous to `index.html`. For example, when someone visits `https://some-ember-app.com`, the contents of the `template/index.hbs` file will be rendered. There is no need to add an entry `this.route('index', { path: '/' });` in `app/router.js` file. The `index` route is implicitly included in order to help reduce verbose declarations in the `app/router.js`. The `app/router.js` file could be empty, and the `index` would still be shown:
212+
- The top-level index route is analogous to `index.html`. For example, when someone visits `https://some-ember-app.com`, the contents of the `template/index.gjs` file will be rendered. There is no need to add an entry `this.route('index', { path: '/' });` in `app/router.js` file. The `index` route is implicitly included in order to help reduce verbose declarations in the `app/router.js`. The `app/router.js` file could be empty, and the `index` would still be shown:
204213

205214
```javascript {data-filename=app/router.js}
206215
Router.map(function() {
207216
});
208217
```
209-
- When a user navigates to `/posts`, the contents of `index.hbs` will be rendered. This is similar to a user navigating to the child route of `/posts`. `/posts/index` is a child route like `/posts/comments` or `/posts/likes`.
218+
- When a user navigates to `/posts`, the contents of `index.gjs` will be rendered. This is similar to a user navigating to the child route of `/posts`. `/posts/index` is a child route like `/posts/comments` or `/posts/likes`.
210219

211220
### When to use an index route
212221

213222
The index route is most helpful for rendering a view when the route has [dynamic segments](#toc_dynamic-segments) defined in it or there are nested routes. In other words, an `index` template is used to show content that should not be present on sibling and child routes. For example, a blog app might have an `index` route that shows a list of all posts, but if a user clicks on a post, they should only see the content for the individual post. Here is how that looks in practice:
214223

215-
A `templates/posts.hbs` file has the following:
224+
A `templates/posts.gjs` file has the following:
225+
226+
```gjs {data-filename=templates/posts.gjs}
227+
228+
import { pageTitle } from 'ember-page-title'
216229
217-
```handlebars {data-filename=templates/posts.hbs}
218-
{{page-title "Posts"}}
219-
<h1>This is the posts template, containing headers to show on all child routes</h1>
220-
{{outlet}}
230+
<template>
231+
{{pageTitle "Posts"}}
232+
<h1>This is the posts template, containing headers to show on all child routes</h1>
233+
{{outlet}}
234+
</template>
221235
```
222236

223-
The `templates/posts/index.hbs` file has the following:
237+
The `templates/posts/index.gjs` file has the following:
224238

225-
```handlebars {data-filename=templates/posts/index.hbs}
226-
{{page-title "Posts"}}
227-
<p>This is the posts/index template with a list of posts</p>
239+
```gjs {data-filename=templates/posts/index.gjs}
240+
import { pageTitle } from 'ember-page-title'
241+
242+
<template>
243+
{{pageTitle "Posts"}}
244+
<p>This is the posts/index template with a list of posts</p>
245+
</template>
228246
```
229247

230-
The `templates/posts/post.hbs` file has the following:
248+
The `templates/posts/post.gjs` file has the following:
249+
250+
```gjs {data-filename=templates/posts/post.gjs}
251+
import { pageTitle } from 'ember-page-title'
231252
232-
```handlebars {data-filename=templates/posts/post.hbs}
233-
{{page-title "Post"}}
234-
<p>This is an individual post, from the posts/post template, used when we enter the /posts/:post_id route</p>
253+
<template>
254+
{{pageTitle "Post"}}
255+
<p>This is an individual post, from the posts/post template, used when we enter the /posts/:post_id route</p>
256+
</template>
235257
```
236258

237259
This is equivalent to having the following entry in `app/router.js` file
@@ -247,18 +269,26 @@ Router.map(function() {
247269

248270
When the user navigates to `/posts/123`, the following markup will be seen:
249271

250-
```handlebars {data-filename=templates/posts/post.hbs}
251-
{{page-title "Posts"}}
252-
<h1>This is the posts template, containing headers to show on all child routes</h1>
253-
<p>This is an individual post, from the posts/post template, used when we enter the /posts/:post_id route</p>
272+
```gjs {data-filename=templates/posts/post.gjs}
273+
import { pageTitle } from 'ember-page-title'
274+
275+
<template>
276+
{{pageTitle "Posts"}}
277+
<h1>This is the posts template, containing headers to show on all child routes</h1>
278+
<p>This is an individual post, from the posts/post template, used when we enter the /posts/:post_id route</p>
279+
</template>
254280
```
255281

256282
When the user navigates to `/posts/`, the following markup will be seen:
257283

258-
```handlebars {data-filename=templates/posts/index.hbs}
259-
{{page-title "Posts"}}
260-
<h1>This is the posts template, containing headers to show on all child routes</h1>
261-
<p>This is the posts/index template with a list of posts</p>
284+
```gjs {data-filename=templates/posts/index.gjs}
285+
import { pageTitle } from 'ember-page-title'
286+
287+
<template>
288+
{{pageTitle "Posts"}}
289+
<h1>This is the posts template, containing headers to show on all child routes</h1>
290+
<p>This is the posts/index template with a list of posts</p>
291+
</template>
262292
```
263293

264294
## Dynamic Segments
@@ -322,9 +352,13 @@ Router.map(function() {
322352
});
323353
```
324354

325-
```handlebars {data-filename=app/templates/not-found.hbs}
326-
{{page-title "Not found"}}
327-
<p>Oops, the page you're looking for wasn't found</p>
355+
```gjs {data-filename=app/templates/not-found.gjs}
356+
import { pageTitle } from 'ember-page-title'
357+
358+
<template>
359+
{{pageTitle "Not found"}}
360+
<p>Oops, the page you're looking for wasn't found</p>
361+
</template>
328362
```
329363

330364
In the above example we have successfully used a wildcard route to handle all routes not managed by our application

guides/release/routing/rendering-a-template.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ Router.map(function() {
1111
});
1212
```
1313

14-
Here, the `posts` route will render the `posts.hbs` template, and
15-
the `posts.new` route will render `posts/new.hbs`.
14+
Here, the `posts` route will render the `posts.gjs` template, and
15+
the `posts.new` route will render `posts/new.gjs`.
1616

1717
Each template will be rendered into the `{{outlet}}` of its parent route's
1818
template. For example, the `posts.new` route will render its template into the
19-
`posts.hbs`'s `{{outlet}}`, and the `posts` route will render its template into
20-
the `application.hbs`'s `{{outlet}}`.
19+
`posts.gjs`'s `{{outlet}}`, and the `posts` route will render its template into
20+
the `application.gjs`'s `{{outlet}}`.

guides/release/routing/specifying-a-routes-model.md

Lines changed: 53 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,14 @@ export default class FavoritePostsRoute extends Route {
5555

5656
Now that data can be used in the `favorite-posts` template:
5757

58-
```handlebars {data-filename=app/templates/favorite-posts.hbs}
59-
{{#each @model as |post|}}
60-
<div>
61-
{{post.title}}
62-
</div>
63-
{{/each}}
58+
```gjs {data-filename=app/templates/favorite-posts.gjs}
59+
<template>
60+
{{#each @model as |post|}}
61+
<div>
62+
{{post.title}}
63+
</div>
64+
{{/each}}
65+
</template>
6466
```
6567

6668
Behind the scenes, what is happening is that the [route's controller](https://api.emberjs.com/ember/release/classes/Route/methods/setupController?anchor=setupController) receives the results of the model hook, and Ember makes the model hook results available to the template. Your app may not have a controller file for the route, but the behavior is the same regardless.
@@ -133,22 +135,24 @@ export default class SongsRoute extends Route {
133135
In the `songs` template, we can specify both models and use the `{{#each}}` helper to display
134136
each record in the song model and album model:
135137

136-
```handlebars {data-filename=app/templates/songs.hbs}
137-
<h1>Playlist</h1>
138+
```gjs {data-filename=app/templates/songs.gjs}
139+
<template>
140+
<h1>Playlist</h1>
138141
139-
<ul>
140-
{{#each @model.songs as |song|}}
141-
<li>{{song.name}} by {{song.artist}}</li>
142-
{{/each}}
143-
</ul>
142+
<ul>
143+
{{#each @model.songs as |song|}}
144+
<li>{{song.name}} by {{song.artist}}</li>
145+
{{/each}}
146+
</ul>
144147
145-
<h1>Albums</h1>
148+
<h1>Albums</h1>
146149
147-
<ul>
148-
{{#each @model.albums as |album|}}
149-
<li>{{album.title}} by {{album.artist}}</li>
150-
{{/each}}
151-
</ul>
150+
<ul>
151+
{{#each @model.albums as |album|}}
152+
<li>{{album.title}} by {{album.artist}}</li>
153+
{{/each}}
154+
</ul>
155+
</template>
152156
```
153157

154158
## Dynamic Models
@@ -201,13 +205,9 @@ export default class PostRoute extends Route {
201205
}
202206
```
203207

204-
Note that currently, if `model` is not specified, Ember will attempt
205-
to automatically find a store and use it for lookup. This behavior
206-
is a common source of confusion and will be removed in future Ember versions.
207-
208208
### Linking to a dynamic segment
209209

210-
There are two ways to link to a dynamic segment from an `.hbs` template using [`<LinkTo>`](../../templates/links/).
210+
There are two ways to link to a dynamic segment from an `.gjs` template using [`<LinkTo>`](../../templates/links/).
211211
Depending on which approach you use, it will affect whether that route's `model` hook is run.
212212
To learn how to link to a dynamic segment from within the JavaScript file, see the API documentation on
213213
[`transitionTo`](https://api.emberjs.com/ember/release/classes/RouterService/methods/transitionTo?anchor=transitionTo)
@@ -216,35 +216,48 @@ instead.
216216
When you provide a string or number to the `<LinkTo>`, the dynamic segment's `model` hook will run when the app transitions to the new route.
217217
In this example, `photo.id` might have an id of `4`:
218218

219-
```handlebars {data-filename=app/templates/photos.hbs}
220-
{{#each @model as |photo|}}
221-
<LinkTo @route="photo" @model={{photo.id}}>
222-
link text to display
223-
</LinkTo>
224-
{{/each}}
219+
```gjs {data-filename=app/templates/photos.gjs}
220+
import { LinkTo } from '@ember/routing';
221+
222+
<template>
223+
{{#each @model as |photo|}}
224+
<LinkTo @route="photo" @model={{photo.id}}>
225+
link text to display
226+
</LinkTo>
227+
{{/each}}
228+
</template>
225229
```
226230

227231
However, if you provide the entire model context, the model hook for that URL segment will _not_ be run.
228232
For this reason, many Ember developers choose to pass only ids to `<LinkTo>` so that the behavior is consistent.
229233

230234
Here's what it looks like to pass the entire `photo` record:
231235

232-
```handlebars {data-filename=app/templates/photos.hbs}
233-
{{#each @model as |photo|}}
234-
<LinkTo @route="photo" @model={{photo}}>
235-
link text to display
236-
</LinkTo>
237-
{{/each}}
236+
```gjs {data-filename=app/templates/photos.gjs}
237+
import { LinkTo } from '@ember/routing';
238+
239+
<template>
240+
{{#each @model as |photo|}}
241+
<LinkTo @route="photo" @model={{photo}}>
242+
link text to display
243+
</LinkTo>
244+
{{/each}}
245+
</template>
238246
```
239247

240248
If you decide to pass the entire model, be sure to cover this behavior in your [application tests](../../testing/testing-application/).
241249

242250
If a route you are trying to link to has multiple dynamic segments, like `/photos/4/comments/18`, be sure to specify all the necessary information for each segment:
243251

244-
```handlebars
245-
<LinkTo @route="photos.photo.comments.comment" @models={{array 4 18}}>
246-
link text to display
247-
</LinkTo>
252+
```gjs
253+
import { LinkTo } from '@ember/routing';
254+
import { array } from '@ember/helper';
255+
256+
<template>
257+
<LinkTo @route="photos.photo.comments.comment" @models={{array 4 18}}>
258+
link text to display
259+
</LinkTo>
260+
</template>
248261
```
249262

250263
Routes without dynamic segments will always execute the model hook.

0 commit comments

Comments
 (0)