I want to define a route in emberjs, that has an optional parameter eg:
/video
and
/video/123
if no parameter is supplied, I want to use a default model/fixture. if a parameter is supplied, then I want to obviously lookup the model using the parameter.
if I then go to a different route, and return to the route without the parameter, I want to use the previously loaded model.
eg:
startup app
/video
- shows my default/fixture model
/video/123
- shows model 123
/another-route
- shows new route
/video
- shows model 123
is this possible?
There is a clean way to do this, although it is slightly "tricky". The idea is to use a nested route to hold the id, but not render it, instead having the parent route be responsible for rendering it using the render helper. When you do it this way, all the logic can live in VideoChoiceController, and it will be used for displaying either the default video or a specific one. When doing it this way, there is no need to explicitly "remember" the last video, the state machine that the route engine represents does it for you.
App.Router.map(function) {
this.resource('video', function(){
this.route('choice', {path: ':video_id'});
});
});
App.VideoRoute = Ember.Route.extend({
model: function(params) {
return App.get('defaultVideo');
},
setupController: function(controller, model) {
var video_choice = this.controllerFor('video.choice')
// this is necessary if you want, for example,
// to display the name or a link to the default video
// when a specific video is being displayed
controller.set('model', model);
if(Ember.isEmpty(video_choice.get('model'))){
video_choice.set('model', model);
}
}
});
App.VideoChoiceRoute = Ember.Route.extend({
model: function(params) {
return this.get('store').find('video', params.video_id);
},
renderTemplate: function() {
// if you don't override renderTemplate to do nothing,
// everything will still work but you will get an assertion
// error that render should only be used once with a
// singleton controller
}
});
<script type="text/x-handlebars">
<div>
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" data-template-name='video'>
<div> attrributes here always refer to the default video: {{name}} </div>
{{render "video.choice"}}
</script>
<script type="text/x-handlebars" data-template-name='video'>
<div>
attrributes here always refer to specific or last video,
or default if a specific video has never been loaded: {{name}}
</div>
</script>
I ended up using a different solution:
this.resource('video', function() {
this.route('index', {path: '/'});
this.route('item', {path: ':id'});
});
These routes support:
/video
- shows my default/fixture model
/video/123
- shows model 123
When the user access to /video
, the VideoIndexRoute must redirect to VideoItemRoute without any id.
var VideoIndexRoute = Em.Route.extend({
afterModel: function() {
// this is the tricky part
this.replaceWith('video.item', '');
}
});
Now, the VideoItemRoute must check if there is any model associated, and when it is missing, it should use the default fixtures or a new one.
var VideoItemRoute = Em.Route.extend({
model: function(param) {
if (param.id) {
return this.store.find('video', param.id);
}
},
setupController: function (controller, model) {
if (!model) {
model = this.store.createRecord('video',{
name: 'default Name'
});
// or use fixture...
}
this._super(controller, model);
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With