When transitioning from one Ember route to another, I am getting the following error:
Error: Object in path item_delet could not be found or was destroyed.
In the routes' renderTemplate
hooks, I'm doing a lot of this kind of thing:
this.render('item_delete', { into: 'item_parent', outlet: 'item_delete' });
... and have a rational tree of parent/child templates. However, when a template, say "item_delete", is rendered into an "routeA", then I click along into "routeB", then go back to "routeA", I get the error. I understand that the view object is getting destroyed when the router exits "routeA" for the purpose of preventing memory leaks. I am unsure why re-entering the route does not re-create/instantiate/connect the view. As a side note, when the error is presented any of the previously rendered views that gets this error message always has its path name shortened by one character, notice "item_delet" instead of "item_delete".
I am using grunt-ember-templates to compile the Handlebars templates, so posting a JSFiddle is a little bit difficult. Just wondering if anyone can "sight read" this code to flag any obvious reasons that the routes or the renderTemplate
hooks may be failing to re-instantiate/connect/etc. the rendered templates. Is there some "activate/deactivate" magic that I can do to prevent views from getting destroyed? (I realize that flies in the face of the intentions behind destroying the view objects in the first place, but I'm willing to hear all options.)
I have an Ember Route map that looks like:
App.Router.map(function () {
this.route('index', { path: '/projects' });
this.resource('items', { path: '/projects/folders' }, function() {
this.resource('item', { path: '/:item_id' }, function() {
this.route('file_uploads', { path: '/file_upload' });
});
});
});
I have routes defined like this:
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('items');
}
});
App.ItemsIndexRoute = Ember.Route.extend({
model: function() {
// Setting up the model
}
, setupController: function(controller, model) {
// Setting up some controllers
}
, renderTemplate: function() {
this.render('index', {
into: 'application'
, outlet: 'application'
, controller: this.controllerFor('items')
});
this.render('navbar', {
into: 'application'
, outlet: 'navbar'
, controller: this.controllerFor('currentUser')
});
this.render('items', {
into: 'index'
, outlet: 'index'
, controller: this.controllerFor('items')
});
this.render('items_toolbar', {
into: 'index'
, outlet: 'items_toolbar'
, controller: this.controllerFor('items')
});
this.render('item_rename', {
into: 'items_toolbar'
, outlet: 'item_rename'
, controller: this.controllerFor('items')
});
this.render('item_delete', {
into: 'items_toolbar'
, outlet: 'item_delete'
, controller: this.controllerFor('items')
});
// ... some more of these...
}
});
App.ItemRoute = Ember.Route.extend({
model: function (params) {
// Building the model for the route
}
, setupController: function(controller, model) {
// Setting up some controllers
}
, renderTemplate: function() {
this.render('index', {
into: 'application'
, outlet: 'application'
, controller: this.controllerFor('items')
});
this.render('navbar', {
outlet: 'navbar'
, into: 'application'
, controller: this.controllerFor('application')
});
this.render('items', {
into: 'index'
, outlet: 'index'
, controller: this.controllerFor('items')
});
this.render('items_toolbar', {
into: 'index'
, outlet: 'items_toolbar'
, controller: this.controllerFor('items')
});
this.render('item_rename', {
into: 'items_toolbar'
, outlet: 'item_rename'
, controller: this.controllerFor('items')
});
this.render('item_delete', {
into: 'items_toolbar'
, outlet: 'item_delete'
, controller: this.controllerFor('items')
});
// ... some more of these...
}
});
App.ItemFileUploadsRoute = Ember.Route.extend({
model: function() {
// Setting up the model
}
, setupController: function(controller, model) {
// Setting up some controllers
}
, renderTemplate: function() {
this.render('file_uploads', {
into: 'application'
, outlet: 'application'
, controller: this.controllerFor('fileUploads')
});
this.render('navbar', {
into: 'application'
, outlet: 'navbar'
, controller: this.controllerFor('application')
});
this.render('items_toolbar', {
into: 'file_uploads'
, outlet: 'items_toolbar'
, controller: this.controllerFor('fileUploads')
});
this.render('item_rename', {
into: 'items_toolbar'
, outlet: 'item_rename'
, controller: this.controllerFor('items')
});
this.render('item_delete', {
into: 'items_toolbar'
, outlet: 'item_delete'
, controller: this.controllerFor('items')
});
// ... some more of these...
}
});
I am reusing some templates and their outlets for different routes/resources. For example, the "items_toolbar" referred to above is in a Handlebars template like this:
<div class="row toolbar">
<div class="col col-lg-6 text-right">
{{outlet submission_options_button}}
{{outlet submission_button}}
{{outlet create_button}}
{{outlet confirm_button}}
{{outlet cancel_button}}
{{outlet folder_actions}}
{{outlet item_rename}}
{{outlet item_delete}}
</div>
</div>
In this template, not all the outlets will get a buffer rendered into them, and in other contexts they will. I'm doing this to avoid undesirable (confusing) conditionals in the Handlebars code (and the usual "isVisible" nonsense). I'm interested in a given template "wearing" its views as needed; in some instances there may be a "create_button" and a "cancel_button" and in other cases there may be a "cancel_button" and a "folder_actions".
Is there any sure-fire way to ensure that when re-entering a route that any objects that were previously rendered in it, then destroyed, could be reconnected, re-initialized, and/or re-rendered?