Ember.js pass params object to linkTo or action helper - ember.js

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 };
}

Related

Dynamic segments for nested ember routes not working

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?

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.

Multiple models to Ember route

I have a list of printers
GradingX.PrintersRoute = Ember.Route.extend({
model: function () {
var printerList = Em.A();
//Ember.
$.getJSON("http://localhost/printers").then(function (data) {
data.forEach(function (item) {
printerList.addObject(item);
}), function () {
alert("$.getJSON failed!");
};
});
return printerList;
},
});
That I'm trying to access from my header
GradingX.HeaderRoute = Ember.Route.extend({
model: function () {
//console.log("test in header model route");
//return Ember.Object.create({
return Ember.RSVP.hash({
printers: What Goes Here?,
otherObjects: More Stuff Here
});
},
});
I'm trying to follow the answer here https://stackoverflow.com/a/20523510/697827, but since I'm not accessing through Ember-Data I don't think this.store.find('printers') is going to get me what I need.
I'm missing something. Please help!
RSVP.hash expects an object with keys and promises as values. So I think that the following could work:
GradingX.HeaderRoute = Ember.Route.extend({
model: function () {
return Ember.RSVP.hash({
printers: $.getJSON("http://localhost/printers"),
otherObjects: $.getJSON("http://localhost/???")
});
},
});
In the referenced answer is used this.store.find, which also returns a promise, but it's resolved with a DS.RecordArray (an array like object provided by ember data). So what matters for RSVP.hash are promises.

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.

Same Ember.JS template for display/edit and creation

I am writing a CRUD application using Ember.JS:
A list of “actions” is displayed;
The user can click on one action to display it, or click on a button to create a new action.
I would like to use the same template for displaying/editing an existing model object and creating a new one.
Here is the router code I use.
App = Ember.Application.create();
App.Router.map(function() {
this.resource('actions', {path: "/actions"}, function() {
this.resource('action', {path: '/:action_id'});
this.route('new', {path: "/new"});
});
});
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('actions');
}
});
App.ActionsIndexRoute = Ember.Route.extend({
model: function () {
return App.Action.find();
}
});
App.ActionRoute = Ember.Route.extend({
events: {
submitSave: function () {
this.get("store").commit();
}
}
});
App.ActionsNewRoute = Ember.Route.extend({
renderTemplate: function () {
this.render('action');
},
model: function() {
var action = this.get('store').createRecord(App.Action);
return action;
},
events: {
submitSave: function () {
this.get("store").commit();
}
}
});
The problem is that when I first display an action, and then come back to create a new one, it looks like the template is not using the newly created record, but use instead the one displayed previously.
My interpretation is that the controller and the template are not in sync.
How would you do that?
Maybe there is a simpler way to achieve this?
Here is a JSBin with the code: http://jsbin.com/owiwak/10/edit
By saying this.render('action'), you are not just telling it to use the action template, but also the ActionController, when in fact you want the action template, but with the ActionNewController.
You need to override that:
this.render('action', {
controller: 'actions.new'
});
Updated JS Bin.