-
-
Notifications
You must be signed in to change notification settings - Fork 511
Convert routing section to route components #2118
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
base: gjs
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ To define a route, run | |
ember generate route route-name | ||
``` | ||
|
||
This creates a route file at `app/routes/route-name.js`, a template for the route at `app/templates/route-name.hbs`, | ||
This creates a route file at `app/routes/route-name.js`, a template for the route at `app/templates/route-name.gjs`, | ||
and a unit test file at `tests/unit/routes/route-name-test.js`. | ||
It also adds the route to the router. | ||
|
||
|
@@ -65,7 +65,7 @@ Router.map(function() { | |
``` | ||
|
||
The route defined above will by default use the `blog-post.js` route handler, | ||
the `blog-post.hbs` template, and be referred to as `blog-post` in any | ||
the `blog-post.gjs` template, and be referred to as `blog-post` in any | ||
`<LinkTo />` components. | ||
|
||
Multi-word route names that break this convention, such as: | ||
|
@@ -77,7 +77,7 @@ Router.map(function() { | |
``` | ||
|
||
will still by default use the `blog-post.js` route handler and the | ||
`blog-post.hbs` template, but will be referred to as `blog_post` in any | ||
`blog-post.gjs` template, but will be referred to as `blog_post` in any | ||
`<LinkTo />` components. | ||
|
||
## Nested Routes | ||
|
@@ -109,17 +109,22 @@ ember generate route posts/new | |
And then add the `{{outlet}}` helper to your template where you want the nested | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we be saying 'route component' rather than 'template'? |
||
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. | ||
|
||
```handlebars {data-filename=templates/posts.hbs} | ||
{{page-title "Posts - Site Title"}} | ||
<h1>Posts</h1> | ||
{{!-- Display posts and other content --}} | ||
{{outlet}} | ||
```gjs {data-filename=templates/posts.gjs} | ||
import { pageTitle } from 'ember-page-title' | ||
|
||
<template> | ||
{{pageTitle "Posts - Site Title"}} | ||
|
||
<h1>Posts</h1> | ||
{{!-- Display posts and other content --}} | ||
{{outlet}} | ||
</template> | ||
``` | ||
|
||
This generates a route for `/posts` and for `/posts/new`. When a user | ||
visits `/posts`, they'll simply see the `posts.hbs` template. (Below, [index | ||
visits `/posts`, they'll simply see the `posts.gjs` template. (Below, [index | ||
routes](#toc_index-routes) explains an important addition to this.) When the | ||
user visits `posts/new`, they'll see the `posts/new.hbs` template rendered into | ||
user visits `posts/new`, they'll see the `posts/new.gjs` template rendered into | ||
the `{{outlet}}` of the `posts` template. | ||
|
||
A nested route name includes the names of its ancestors. | ||
|
@@ -134,7 +139,7 @@ routes, it will load a template with the same name (`application` in | |
this case) by default. | ||
You should put your header, footer, and any other decorative content | ||
here. All other routes will render | ||
their templates into the `application.hbs` template's `{{outlet}}`. | ||
their templates into the `application.gjs` template's `{{outlet}}`. | ||
|
||
This route is part of every application, so you don't need to | ||
specify it in your `app/router.js`. | ||
|
@@ -200,38 +205,51 @@ replace the `{{outlet}}` in the `posts` template with the | |
|
||
The following scenarios may help with understanding the `index` route: | ||
|
||
- 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: | ||
- 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: | ||
|
||
```javascript {data-filename=app/router.js} | ||
Router.map(function() { | ||
}); | ||
``` | ||
- 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`. | ||
- 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`. | ||
|
||
### When to use an index route | ||
|
||
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: | ||
|
||
A `templates/posts.hbs` file has the following: | ||
A `templates/posts.gjs` file has the following: | ||
|
||
```gjs {data-filename=templates/posts.gjs} | ||
|
||
```handlebars {data-filename=templates/posts.hbs} | ||
{{page-title "Posts"}} | ||
<h1>This is the posts template, containing headers to show on all child routes</h1> | ||
{{outlet}} | ||
import { pageTitle } from 'ember-page-title' | ||
|
||
<template> | ||
{{pageTitle "Posts"}} | ||
<h1>This is the posts template, containing headers to show on all child routes</h1> | ||
{{outlet}} | ||
</template> | ||
``` | ||
|
||
The `templates/posts/index.hbs` file has the following: | ||
The `templates/posts/index.gjs` file has the following: | ||
|
||
```gjs {data-filename=templates/posts/index.gjs} | ||
import { pageTitle } from 'ember-page-title' | ||
|
||
```handlebars {data-filename=templates/posts/index.hbs} | ||
{{page-title "Posts"}} | ||
<p>This is the posts/index template with a list of posts</p> | ||
<template> | ||
{{pageTitle "Posts"}} | ||
<p>This is the posts/index template with a list of posts</p> | ||
</template> | ||
``` | ||
|
||
The `templates/posts/post.hbs` file has the following: | ||
The `templates/posts/post.gjs` file has the following: | ||
|
||
```handlebars {data-filename=templates/posts/post.hbs} | ||
{{page-title "Post"}} | ||
<p>This is an individual post, from the posts/post template, used when we enter the /posts/:post_id route</p> | ||
```gjs {data-filename=templates/posts/post.gjs} | ||
import { pageTitle } from 'ember-page-title' | ||
|
||
<template> | ||
{{pageTitle "Post"}} | ||
<p>This is an individual post, from the posts/post template, used when we enter the /posts/:post_id route</p> | ||
</template> | ||
``` | ||
|
||
This is equivalent to having the following entry in `app/router.js` file | ||
|
@@ -247,18 +265,26 @@ Router.map(function() { | |
|
||
When the user navigates to `/posts/123`, the following markup will be seen: | ||
|
||
```handlebars {data-filename=templates/posts/post.hbs} | ||
{{page-title "Posts"}} | ||
<h1>This is the posts template, containing headers to show on all child routes</h1> | ||
<p>This is an individual post, from the posts/post template, used when we enter the /posts/:post_id route</p> | ||
```gjs {data-filename=templates/posts/post.gjs} | ||
import { pageTitle } from 'ember-page-title' | ||
|
||
<template> | ||
{{pageTitle "Posts"}} | ||
<h1>This is the posts template, containing headers to show on all child routes</h1> | ||
<p>This is an individual post, from the posts/post template, used when we enter the /posts/:post_id route</p> | ||
</template> | ||
``` | ||
|
||
When the user navigates to `/posts/`, the following markup will be seen: | ||
|
||
```handlebars {data-filename=templates/posts/index.hbs} | ||
{{page-title "Posts"}} | ||
<h1>This is the posts template, containing headers to show on all child routes</h1> | ||
<p>This is the posts/index template with a list of posts</p> | ||
```gjs {data-filename=templates/posts/index.gjs} | ||
import { pageTitle } from 'ember-page-title' | ||
|
||
<template> | ||
{{pageTitle "Posts"}} | ||
<h1>This is the posts template, containing headers to show on all child routes</h1> | ||
<p>This is the posts/index template with a list of posts</p> | ||
</template> | ||
``` | ||
|
||
## Dynamic Segments | ||
|
@@ -322,9 +348,13 @@ Router.map(function() { | |
}); | ||
``` | ||
|
||
```handlebars {data-filename=app/templates/not-found.hbs} | ||
{{page-title "Not found"}} | ||
<p>Oops, the page you're looking for wasn't found</p> | ||
```gjs {data-filename=app/templates/not-found.gjs} | ||
import { pageTitle } from 'ember-page-title' | ||
|
||
<template> | ||
{{pageTitle "Not found"}} | ||
<p>Oops, the page you're looking for wasn't found</p> | ||
</template> | ||
``` | ||
|
||
In the above example we have successfully used a wildcard route to handle all routes not managed by our application | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,5 +16,5 @@ the `posts.new` route will render `posts/new.hbs`. | |
|
||
Each template will be rendered into the `{{outlet}}` of its parent route's | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Text above here references hbs |
||
template. For example, the `posts.new` route will render its template into the | ||
`posts.hbs`'s `{{outlet}}`, and the `posts` route will render its template into | ||
the `application.hbs`'s `{{outlet}}`. | ||
`posts.gjs`'s `{{outlet}}`, and the `posts` route will render its template into | ||
the `application.gjs`'s `{{outlet}}`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,17 @@ | ||
<div class="cta"> | ||
<div class="cta-note"> | ||
<div class="cta-note-body"> | ||
<div class="cta-note-heading">Zoey says...</div> | ||
<div class="cta-note-message"> | ||
<p>This document has been updated to use the <a href="../../components/template-tag-format/">Template Tag Format</a> and assumes that you have generated your application using the <code style="white-space: nowrap">--strict</code> argument.</p> | ||
|
||
<p>The Ember Guides are being gradually updated at the moment so you might find some pages using the older hbs format.</p> | ||
</div> | ||
</div> | ||
<img src="/images/mascots/zoey.png" role="presentation" alt=""> | ||
</div> | ||
</div> | ||
|
||
A route's JavaScript file is one of the best places in an app to make requests to an API. | ||
In this section of the guides, you'll learn how to use the | ||
[`model`](https://api.emberjs.com/ember/release/classes/Route/methods/model?anchor=model) | ||
|
@@ -55,12 +69,14 @@ export default class FavoritePostsRoute extends Route { | |
|
||
Now that data can be used in the `favorite-posts` template: | ||
|
||
```handlebars {data-filename=app/templates/favorite-posts.hbs} | ||
{{#each @model as |post|}} | ||
<div> | ||
{{post.title}} | ||
</div> | ||
{{/each}} | ||
```gjs {data-filename=app/templates/favorite-posts.gjs} | ||
<template> | ||
{{#each @model as |post|}} | ||
<div> | ||
{{post.title}} | ||
</div> | ||
{{/each}} | ||
</template> | ||
``` | ||
|
||
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 +149,24 @@ export default class SongsRoute extends Route { | |
In the `songs` template, we can specify both models and use the `{{#each}}` helper to display | ||
each record in the song model and album model: | ||
|
||
```handlebars {data-filename=app/templates/songs.hbs} | ||
<h1>Playlist</h1> | ||
```gjs {data-filename=app/templates/songs.gjs} | ||
<template> | ||
<h1>Playlist</h1> | ||
|
||
<ul> | ||
{{#each @model.songs as |song|}} | ||
<li>{{song.name}} by {{song.artist}}</li> | ||
{{/each}} | ||
</ul> | ||
<ul> | ||
{{#each @model.songs as |song|}} | ||
<li>{{song.name}} by {{song.artist}}</li> | ||
{{/each}} | ||
</ul> | ||
|
||
<h1>Albums</h1> | ||
<h1>Albums</h1> | ||
|
||
<ul> | ||
{{#each @model.albums as |album|}} | ||
<li>{{album.title}} by {{album.artist}}</li> | ||
{{/each}} | ||
</ul> | ||
<ul> | ||
{{#each @model.albums as |album|}} | ||
<li>{{album.title}} by {{album.artist}}</li> | ||
{{/each}} | ||
</ul> | ||
</template> | ||
``` | ||
|
||
## Dynamic Models | ||
|
@@ -216,25 +234,33 @@ instead. | |
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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. References above here to hbs |
||
In this example, `photo.id` might have an id of `4`: | ||
|
||
```handlebars {data-filename=app/templates/photos.hbs} | ||
{{#each @model as |photo|}} | ||
<LinkTo @route="photo" @model={{photo.id}}> | ||
link text to display | ||
</LinkTo> | ||
{{/each}} | ||
```gjs {data-filename=app/templates/photos.gjs} | ||
import { LinkTo } from '@ember/routing'; | ||
|
||
<template> | ||
{{#each @model as |photo|}} | ||
<LinkTo @route="photo" @model={{photo.id}}> | ||
link text to display | ||
</LinkTo> | ||
{{/each}} | ||
</template> | ||
``` | ||
|
||
However, if you provide the entire model context, the model hook for that URL segment will _not_ be run. | ||
For this reason, many Ember developers choose to pass only ids to `<LinkTo>` so that the behavior is consistent. | ||
|
||
Here's what it looks like to pass the entire `photo` record: | ||
|
||
```handlebars {data-filename=app/templates/photos.hbs} | ||
{{#each @model as |photo|}} | ||
<LinkTo @route="photo" @model={{photo}}> | ||
link text to display | ||
</LinkTo> | ||
{{/each}} | ||
```gjs {data-filename=app/templates/photos.gjs} | ||
import { LinkTo } from '@ember/routing'; | ||
|
||
<template> | ||
{{#each @model as |photo|}} | ||
<LinkTo @route="photo" @model={{photo}}> | ||
link text to display | ||
</LinkTo> | ||
{{/each}} | ||
</template> | ||
``` | ||
|
||
If you decide to pass the entire model, be sure to cover this behavior in your [application tests](../../testing/testing-application/). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. handlebars below here |
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Above here (I cannot comment on unedited lines) are references to
template
and examples of hbs that need to be converted.