Nested index route not rendering in outlet properly - ember.js

I'm trying to render taking-cash/index inside taking-cash's {{outlet}}:
router.js:
this.route('retirement-options', function () {
this.route('taking-cash');
It doesn't render it inside the outlet, unless I explicitly specify the /index path:
this.route('retirement-options', function () {
this.route('taking-cash', function() {
this.route('index', { path: '' });
});
});
Why isn't /index implied, can I not specify it in router.js?

Ember provides an index route automatically only for routes, which have at least one other child.
Let's have a look at your example:
this.route('retirement-options', function () {
this.route('taking-cash');
});
This creates three routes:
retirement-options
retirement-options.index
retirement-options.taking-cash
retirement-options.index and retirement-options.taking-cash both share the same parent route retirement-options.
retirement-options is not navigateable itself. It will always resolve to the retirement-options.index route unless transition targets taking-cash child route explicitly.
As soon as you add another child route to retirement-options.taking-cash an index route will be created for it automatically by Ember.
You can enforce an explicit index route by creating a route as you have shown. But there is not much value of having an index route as only leaf node.
Please find more information about the Index Routes in the guides: https://guides.emberjs.com/release/routing/defining-your-routes/#toc_index-routes

Ember will provide an index route automatically only for routes indeed, but it does not need to have a child specifically. It is actually the callback function that has to be present.
So looking at the example,
this.route('retirement-options', function() {
this.route('taking-cash', function() {
this.route('index', { path: '' });
});
});
the index part is not mandatory specifically. As soon as you have a callback function declared, the index will be there.
This would do exactly the same as the example above.
this.route('retirement-options', function() {
this.route('taking-cash', function() {});
});

Related

Emberjs: How to get to a route parameter passed in via url in controller

Consider routes:
this.resource('things', {path: '/things/:id'}, function () {
this.route('edit');
});
Inside controller of the edit, how do I access the :id?
You can use the paramsFor method in the route to get parent route parameters.
So in your case you can also use the setupController hook of the edit route,
setupController(controller,model){
this._super(...arguments);
let { id } = this.paramsFor(this.routeName);
controller.set('thingsId',id);
}

Disable application.hbs for a single route in Ember.JS

Simply, the web app needs to use the application.hbs template 99% of the time but for a single route, I would like to disable it and render only the route template.
Like 'Layout=null;' in asp.net
Thanks in advance.
The shortest answer is that you need to nest all the routes that share a layout under a common parent route, since you can't remove the application template. This can be done in a couple different ways, depending on the goal.
If they all share a URL segment, you can put then under a common parent:
Router.map(function() {
this.route('pretty-layout', function() {
this.route('page-1'); // http://localhost:4200/pretty-layout/page-1
this.route('page-2'); // http://localhost:4200/pretty-layout/page-2
});
});
You can override the top-level index route. You'll likely need to move the current application.index to application.index.index:
Router.map(function() {
this.route('index', { path: '/' }, function() {
this.route('page-1'); // http://localhost:4200/page-1
this.route('page-2'); // http://localhost:4200/page-2
});
});

How are ember links to reused nested routes defined using link-to?

Using the example route defined below how can a link be defined to /post/123/comments?
Router.map(function() {
this.route('post', { path: '/post/:post_id' }, function() {
this.route('edit');
this.route('comments', { resetNamespace: true }, function() {
this.route('new');
});
});
this.route('comments');
});
Since resetNamespace: true is set on comments, the route post.comments does not exist. Otherwise the following would work.
{{#link-to "post.comments" "123"}}Link{{/link-to}}
When trying to link to news using the comment id, the error More context objects were passed than there are dynamic segments for the route: comments occurs.
{{#link-to "comments" "123"}}Link{{/link-to}}
An example of the second case can be seen here: https://ember-twiddle.com/d9f3b5e692573c80e803
Thanks to locks for pointing me in the direction. The specific issue is how to reuse as much of the route and template as possible for different paths.
router.js:
Router.map(function() {
this.route('post', { path: '/post/:post_id' }, function() {
this.route('edit');
this.route('comments', function() {
this.route('new');
});
});
this.route('comments');
});
routes/post/comments.js:
import Comments from '../comments';
export default Comments.extend({
renderTemplate() {
this.render('comments');
}
});
This will extend the existing comments route to reuse the model and actions defined in the base route. The renderTemplate is still necessary to load the comments template instead of the post.comments template.
Since you're resetting the namespace, you are effectively overriding one of the comments route with the other. You're doing something akin to
obj['comments'] = firstRoute;
obj['comments'] = secondRoute;
Route names need to be unique, which they would be if you didn't reset the namespace, as well as the path. If two routes have the /foobar path, then Ember won't know which one to transition to.
If what you want is to reuse parts from other routes, there are ways to do that.

What is the difference between router and route in Emberjs

What is the difference between router and route in emberjs? I wanted an implementable explanation if possible
Router - ember application will have one Router, it manages transitions between routes and it contains map of all routes. You specify map of routes like so:
App.Router.map(function(){
this.route('post', { path: '/post/:post_id' }, function() {
this.route('edit');
this.route('comments', { resetNamespace: true }, function() {
this.route('new');
});
});
});
from which Router is able to identify structure of routes and their accepting params. It activates corresponding Route when you navigate to particular path/url in browser ember router docs
Route - for each path/route you will have Route object, when you change path/url in browser corresponding Route gets activated for that path and set up everything (controller, template) which relate to that route (that has same name usually).
ember route docs
read more
The practical difference between these two is that resource may contain other routes, whereas route cannot. Additionally, this.resource automatically creates an index route when it sees you have sub-routes.
App.Router.map(function() {
this.resource('records', function() {
// this.route('index') is created automatically in here
this.route('new');
});
this.route('about');
});
While you could always use this.resource and have things work correctly, this.route explicitly creates router leaf states and therefore will lead to a more precise and efficient graph of states for your app.

Ember. Routes. The same name in nested routes, routes lookup

Is it impossible to have nested routes with the same names? For example:
// url - category/12345/card/id99
this.resource('category', { path: '/category/:category_id' }, function () {
this.resource('card', { path: 'card/:card_id' });
});
// url - semantic/books/card/id99
this.resource('semantic', { path: '/semantic/:semantic_id' }, function () {
this.resource('card', { path: 'card/:card_id' });
});
When I call transitionTo('card') router lookups only last version of route 'card'
Looks like router has plain routes list and routes with the same names constantly overriden by last.
I'm wrong?
Imagine hitting 'card/:card_id' directly in the browser. The router cannot differentiate the context of that route from one parent or another. A more appropriate way to handle this issue pointed out in your related question (Ember. Making modal view that has its own route) would be to have a separate route that you pass a 'previous route' context to.
yes, for version v.1 it's impossible.