I have 2 routes - sessions and session (because I want to present them in 2 different pages)
App.Router.map(function () {
this.route("sessions", { path: "/sessions" });
this.route("session", { path: "/sessions/:session_id" });
}
When I go to: #/sessions - I get a nice table that I drew, and when I click the link I made
in the handlebar view:
{{#each model}}
<tr>
<td>{{#link-to 'session' this}}{{this.id}}{{/link-to}}</td>
</tr>
It works - the separate handlebars of the session is drawn
When I go directly to #/sessions/4 I'm getting an error:
Assertion Failed: You may not pass "undefined" as id to the store's find method
The routes:
App.SessionsRoute = Ember.Route.extend({
model: function() {
return this.store.find('session');
}
});
App.SessionRoute = Ember.Route.extend({
model: function(params) {
return this.get('store').find('session', params.session_id);
}
});
For the dynamic segments to work, you need to use this.resource when declaring your routes:
App.Router.map(function () {
this.route("sessions", { path: "/sessions" });
this.resource("session", { path: "/sessions/:session_id" });
}
Related
i am trying to build my first emberjs app and i wonder how i can save the state of a nested route to rebuild that state when the top route is revisted in the current session.
To give an example:
Lets Say a user switches from /overview/item1 to /info and then returns to
/overview/ and want to redirect him to /overview/item1
HTML
<div id="navigation">
{{#link-to 'info' class='link' }}Info{{/link-to}}
{{#link-to 'overview' class='link'}} Overview {{/link-to}}
</div>
JS
App.Router.map(function(){
this.route('info');
this.resource('overview', function () {
this.resource('item', { path : '/:item_id'});
});
});
it would be really nice if somebody could give me a hint to the right approach of this.
There are various ways for achieving your goal. Basically, you need to store state of last visited overview/:item_id route in the parent route or controller. Then, you need to check this state before resolving model of overview route. If state is not null (user was selected some item from overview/:item_id), abort current transition and start the new one (to
overview/:selected_item_id).
Schematic solution in code:
// 1st approach
App.OverviewController = Ember.ObjectController.extend({
selectedItem: null
});
App.OverviewRoute = Ember.Route.extend({
beforeModel: function(transition) {
if (this.get('controller.selectedItem')) {
transition.abort();
this.transitionTo('overview.item', this.get('selectedItem'));
}
}
});
App.OverviewItemRoute = Ember.Route.extend({
afterModel: function(model) {
this.controllerFor('overview').set('selectedItem', model);
}
});
// 2nd approach (less code)
App.OverviewRoute = Ember.Route.extend({
beforeModel: function(transition) {
if (this.get('controller.selectedItem')) {
transition.abort();
this.transitionTo('overview.item', this.get('selectedItem'));
}
},
setupController: function(controller) {
controller.reopen({ selectedItem: null });
}
});
App.OverviewItemRoute = Ember.Route.extend({
afterModel: function(model) {
this.controllerFor('overview').set('selectedItem', model);
}
});
It's important to keep the item itself, not it's id, because it'll way more easier to load overview/:item_id route in the future (passing stored model in this.transitionTo('overview.item', item)).
I am trying to {{#link-to}} the '/edit' route of a specific instance of a model, 'category/2' making route to 'category/2/edit'.
The problem is when I use the url 'category/2/edit' the page remains on the 'category/2' page except that all of the attributes defined in the model for 'category' like {{CategoryType}}, for instance, disappear.
I don't receive a single error while doing this.
Without further ado, here is my code.
router.js ----
this.resource('category', { path: '/category/:category_id' }, function() {
this.route('edit');
});
category.hbs ----
Notes: {{CategoryName}} initially does show up when the page first loads. Only when the page is reloaded or when I try to link to the 'edit' does it disappear.
Category: {{ProjectName}}
{{#link-to 'this.edit'}}<button>Edit this</button>{{/link-to}}
category_route.js ----
Notes: *I'm defining :category_id in the model*
VpcYeoman.CategoryRoute = Ember.Route.extend({
model: function(params) {
return {
id: params.category_id
};
}
});
category_model.js ----
Notes: I cut out the other fixtures to simply this
VpcYeoman.Category = DS.Model.extend({
CategoryName: DS.attr('string'),
workflow: DS.belongsTo('category', {
polymorphic: true
}),
classNameBindings: ['isAdministrator']
});
VpcYeoman.Category.FIXTURES=[
{
id: 2,
RecordCategoryID: 2,
Name: "Nilport",
CategoryName: "Broden Cannon Project"
}
];
I appreciate this guys!
Include an {{outlet}} in category.hbs
You may also have to set the model for the edit route:
VpcYeoman.CategoryEditRoute = Ember.Route.extend({
model: function(params) {
return {
id: params.category_id
};
}
});
I'm building an ember.js app which has a model called "Programme".
A user can drill down to a programme by going:
Genre > Subgenre > Programme or Folder > List > Programme
Here's my router:
this.resource('mylists', { path: '/' }, function() {
this.resource('folder', { path: '/folder/:folder_id' }, function() {
this.resource('list', { path: '/list/:list_id' }, function() {
this.resource('programme', { path: '/programme/:programme_id' });
});
});
});
this.resource('catalogue', function() {
this.resource('genre', { path: '/genre/:genre_id' }, function() {
this.resource('subgenre', { path: '/subgenre/:subgenre_id' }, function() {
this.resource('programme', { path: '/programme/:programme_id' });
});
});
});
The UI needs to be deeply nested (the genre view renders in the outlet of the catalogue template, the subgenre in the outlet of the genre template... and so forth).
The problem I have is as both generated routes are called ProgrammeRoute when I linkTo the programme route inside the list template, it actually goes to the programme route nested in the subgenre route.
What should I be doing here?
To work around it I've named one route ListProgrammeRoute and SubgenreProgrammeRoute but that leads to some duplication.
Have you tried using the link-to helper with multiple models?
{{link-to 'mylists.folder.list.programme' aFolder aList aProgramme}}
I'm having an issue making a nested route available in Ember.js
App.Router.map(function() {
this.resource('home', { path: '/' });
this.resource('form', { path: '/forms/:form_id' }, function() {
this.route('newRecord');
});
I have the parent route...
App.FormRoute = Ember.Route.extend({....
Which is working.
Next I have...
App.FormNewRecordRoute = Ember.Route.extend({
afterModel: function() {
this.set('newRecord', this.modelFor('form');
}
});
Normally I get the URL with something like localhost/forms/9087
With the child route I'm getting localhost/undefined/newRecord
I'm guessing that 'localhost/undefined/newRecord' is coming from something like {{#link-to 'newRecord'}}. It should probably be {{#link-to 'form.newRecord'}}.
I've got a problem getting the linkTo Handlebar helper to work
I've got this route setup:
this.resource("contact", function(){
this.route('new');
this.route('show', { path: "/:contactid" });
this.route('edit', { path: "edit/:contactid" });
}
in my template I have the following code:
{{#each entry in controller.entries}}
{#linkTo "contact.show" entry href="true" }}test {{firstname}} {{lastname}}{{/linkTo}}
{{/each}}
The resulting link though is /contact/show/undefined
What am I doing wrong?
Sidenote: I'm not using Ember.Data and the models.
Ember expects that parameters follow the convention modelname_id, so the route should be changed to:
this.resource("contact", function(){
this.route('new');
this.route('show', { path: "/:contact_id" });
this.route('edit', { path: "edit/:contact_id" });
}
This should work, assuming that entry.get("id") is defined.
See http://emberjs.com/guides/routing/specifying-a-routes-model/ for detail.
Implement serialize in the router to override the default behavior of id. For example I have a route that looks like:
this.route( 'date', { path: '/:begin/:end'} );
and the route will look like
Em.Route.extend( {
serialize: function( model, params ) {
return { begin: model.begin.valueOf(), end: model.end.valueOf() };
}
} );