Dynamic segments for nested ember routes not working - ember.js

I have a nested route structure:
//router.js
this.route('maps', { path: '/maps' }, function () {
this.route('show', { path: '/:id' }, function () {
this.route('display', { path: '/display' }),
this.route('layers', function () {
this.route('create')
})
});
});
my understanding here is that I should have a route maps.show.display that should take a single dynamic segment like maps/1/display
However when I go to transition or link to this ie:
//maps route
afterModel: function (resolvedModel) {
var newestFlight = resolvedModel.content[0];
var newestMap = newestFlight.get('map');
this.transitionTo('maps.show.display', newestMap);
}
or
{{#link-to 'maps.show.display' id}}show map{{/link-to}}
I get an error:
Error while processing route: maps.index More context objects were passed than there are dynamic segments for the route: maps.show.index
It makes it even weirder that this route accepted the same dynamic segment when it was just maps/display so I don't understand why nesting it further breaks it.
Any ideas as to what I'm doing wrong would be greatly appreciated
edit: interestingly, this awesome tool
also seems to agree that I should have a dynamic segment here if you post my route in there

It works fine for me: http://emberjs.jsbin.com/rofowuneni/1/edit?html,css,js,output
BTW I think this:
this.route('display', { path: '/display' });
this.route('layers', function () {
this.route('create')
});
Is supposed to be (not that it matters):
this.route('display', { path: '/display' });
this.route('layers', function () {
this.route('create');
});
What's your ember version?

Related

Ember JS - routing from resourse to route

i'm trying to update and ember project from version 2.x to version 3.x, and one of my first issue is that in the route file i get this.resouce is not defined. i belive this was deprecated. the code looks like this :
this.route('objects', function () {
this.route('search', { path: '/' }, function () {
this.resource('objects.items', { path: '/:search_id' }, function () {
this.resource('objects.item', { path: '/item/:item_id'}, function () {
this.route('general', { path: '/' });
this.route('tab', { path: '/tab/:tab' });
this.route('relations');
this.route('diagram');
this.route('comments');
this.route('sources');
this.route('views');
});
});
});
});
i've tried to simply change the resource to route and give resetNameSpace: true attribute, but didn't help. also i've tried various combinations, but without luck.
anyone with experience can help me redo this routing to be compatible with the latest ember?
As this.resource() is actually an old Ember way of resetting the namespace, the resetNameSpace: true attribute does indeed do the same!
Because you used this.resource('objects.items'), you actually created a resetted namespace where objects was the route.
So your new router would look something like¹:
this.route('objects', function () {
this.route('search', { path: '/'});
this.route('items', { path: '/:search_id'});
this.route('item', { path: '/item/:item_id' }, function () {
this.route('general', { path: '/' });
this.route('tab', { path: '/tab/:tab' });
this.route('relations');
this.route('diagram');
this.route('comments');
this.route('sources');
this.route('views');
});
});
This way you could still use transitionToRoute("objects.item.general", id).
¹ Notice no resetNameSpace flag is used!

Ember.js: there is no route named 'new-table'

Here are my routes definition:
Router.map(function() {
this.resource('servers', { path: '/' }, function() {
this.resource('server', { path: '/servers/:serverid'}, function () {
this.resource('databases', { path: '/databases' }, function () {
this.resource('database', { path: '/:databaseid'}, function () {
this.resource('catalogues', { path: '/catalogues' });
this.resource('eventtriggers', { path: '/eventtriggers' });
this.resource('extensions', { path: '/extensions' });
this.resource('schemas', { path: '/schemas' }, function () {
this.resource('schema', { path: '/:schemaid' }, function () {
this.resource('tables', { path: '/tables' }, function () {
this.route('new-table', function () {});
this.resource('table', { path: '/:tableid' });
});
});
});
this.resource('replication', { path: '/replication' });
});
});
});
});
});
And the code used to generate link to new-table route goes as follows:
{{#link-to 'new-table' schema.database.server.id schema.database.id schema.id}}
And this gives me the error mentioned in this question's topic. However when I replace this.route call to this.resource everything works fine. So what am I doing wrong here? I'm using ember 1.13.2.
A resource defines the main entry point of a link-to. So if you create a resource new-table you can access it via new-table in the link-to helper. Routes on the other hand are children of a resource or another route, they should be prefixed with their parent route or resource. So in the example you gave, you can link to the new-table route by using tables.new-table.

Can Ember handle multiple routes to a single resource?

I want to show the profile page on my web app either by username or user_id. I've tried the following with no success, any ideas?
MyApplication.Router.map(function () {
this.resource('user', { path: '/user' }, function () {
this.resource('profile', {path: '/profile/id/:user_id'});
this.resource('profile', {path: '/profile/:user_username'});
});
this.resource('notFound', {path: '/notfound'});
});
It seems Ember shouldn't really be used in this way. I've read through issues 551 and 571 on Embers Github. I think it's best to stick with showing a user by id to avoid working against the framework.
You can merge those two resources into one as follows:
MyApplication.Router.map(function () {
this.resource('user', { path: '/user' }, function () {
this.resource('profile', {path: '/profile/id/:value'});
});
});
MyApplication.ProfileRoute = Ember.Route.extend({
model: function(params) {
var value = params.value;
if (isNaN(value)) {
return this.store.find('user', { username: value });
} else {
return this.store.find('user', value);
}
}
});
If the value in the URL is a number it will do a findById; otherwise it will do a findQuery. Obviously this approach will fail if some username is a number.
If the URL is the important part for you, you could change the resource names and keep the url prefix the same, for example:
MyApplication.Router.map(function () {
this.resource('user', { path: '/user' }, function () {
this.resource('profileByUserId', {path: '/profile/id/:user_id'});
this.resource('profileByUsername', {path: '/profile/:user_username'});
});
this.resource('notFound', {path: '/notfound'});
});
Hope it helps.
May be with nested routes for the profile resource
MyApplication.Router.map(function () {
this.resource('user', { path: '/user' }, function () {
this.resource('profile', function(){
this.route('byid',{path: '/id/:user_id'});
this.route('byname',{path: '/name/:user_username'});
});
});
this.resource('notFound', {path: '/notfound'});
});
But remember to implement serialize for the definition of the route with user_name
http://emberjs.com/guides/routing/defining-your-routes/
The previos aproach is also valid IMHO

Ember.js pass params object to linkTo or action helper

Is there a way to pass a params object to a linTo or action helper?
I have an object and it needs compound keys. I am using Ember Model and had to modify the adapter. In the Router that gets the initial object i pass a params object with the necessary keys. My problem is trying to do the same thing when using either a linkTo or action with a transitionToRoute. Neither hit the router again as far as I can tell.
Im coming back to this questions. Im still not sure the proper way to handle this.
App.Router.map(function () {
this.resource("clients", { path: 'clients' }, function () {
this.resource("client", { path: ':client_id' }, function () {
this.resource("claims", function () {
this.resource('claim', { path: ':claim_id/:claim_sub' }, function () {
this.resource('lines', { path: 'lines' }, function () {
this.resource('line', { path: ':line_id' }, function () {
this.resource('flags', function () {
this.resource('flag', { path: ':flag_id' });
});
});
this.route('claim_lines');
});
});
});
});
});
this.route("errors", { path: '/errors/:error_id' });
});
When i link to anything under the claim, where the compound slugs are, i get those set to undefined.
UPDATE
The serialize was just what i needed.
App.ClaimRoute = Nucleus.Route.extend({
model: function (params) {
params.client_id = this.modelFor('client').get('client_id');
return App.Claim.find('claim', params);
},
serialize: function (model) {
return { claim_id: model.get('cla_seq'), claim_sub: model.get('cla_sub') };
}
});
I think a code example will be most helpful, but to try to answer your question, yes you can pass an object to linkTo with something like the following:
{{#linkTo routename params}}Text for Link{{/linkTo}}
Then for the route code matching the route name, you can take params as a parameter when you define the serialize function and use them to build the URL to match the routing segments defined in your router:
serialize: function(params) {
// params.property1 and params.property2
return { segment_1: params.property1, segment_2: params.property2 };
}

Routing names with ember.js

I have a router like this
App.Router.map(function () {
this.route("about");
this.resource("invoices", { path: "/invoices" }, function () {
this.resource("invoices.show", { path: "/:id" });
this.resource("invoices.update", { path: "/:id/edit" });
this.route("create");
});
});
and to generate links to the various routes and resources I have this
<nav>
{{#linkTo "invoices.index"}}Invoices{{/linkTo}}
{{#linkTo "invoices.show" 1}}Invoice{{/linkTo}}
{{#linkTo "invoices.create"}}New invoice{{/linkTo}}
</nav>
Why do I have to use invoices.show for the name of the show resource and then reference it as invoices.show but I can use create for the route and then reference it as invoices.create?
Ideally my router would be
App.Router.map(function () {
this.route("about");
this.resource("invoices", { path: "/invoices" }, function () {
this.resource("show", { path: "/:id" });
this.resource("update", { path: "/:id/edit" });
this.route("create");
});
});
and it would auto-prefix the resource names since they are nested within the invoices resource. Right?
Yes, the nested resources can stack their names, and you should be able to reference a nested route with dot notation.
However, you will want to do something more like:
this.resource("invoices", { path: "/invoices" }, function () {
// invoices.show
this.resource("show", { path: "/:id" }, function() {
// invoices.show.update
this.route("update", { path: "/edit" });
});
// invoices.create
this.route("create");
});
since your update operation relies on the object supplied to the show route.
Basically nested elements that rely on the same, or a subset of resources used in a parent route should be defined as resource mappings. Leaf nodes can be defined as basic routes.