ember router v2 goBack functionality - ember.js

In router V1 you can make a simple goBack functionality like this:
App.Router = Ember.Router.extend({
root: Ember.Route.extend({
index: Ember.Route.extend({
route: '/',
redirectsTo: 'posts'
}),
posts: Ember.Route.extend({
route: '/posts',
showPost: Ember.Route.transitionTo('post'),
connectOutlets: function(router){
router.get('applicationController').
connectOutlet('posts',App.Post.find());
}
}),
post: Ember.Route.extend({
route: '/posts/:post_id',
goBack: Ember.Route.transitionTo('posts'),
connectOutlets: function(router, post) {
router.get('applicationController').connectOutlet('post', post);
}
})
})
});
I'm trying to do the same thing in router v2 and came up with the following solution:
App.ApplicationController = Ember.Controller.extend({
currentPathDidChange: function () {
this.set('_previousPath', this.get('_currentPath'));
this.set('_currentPath', this.get('currentPath'));
}.observes('currentPath')
});
App.GobackRoute = Ember.Route.extend({
redirect: function (model) {
var previousPath = this.controllerFor('application').get('_previousPath');
var parts = previousPath.split(".");
var router = this.get('router');
if (router.hasRoute(parts[parts.length - 1])) {
this.transitionTo(parts[parts.length - 1]);
} else if (router.hasRoute(parts[parts.length - 2] + "." + parts[parts.length - 1])) {
this.transitionTo(parts[parts.length - 2] + "." + parts[parts.length - 1]);
} else {
Ember.Logger.warn('No route for: %s', previousPath);
}
}
});
Isn't there a much simpler solution to this?
jsFiddle
I would like to reuse the routes, controllers, etc... without resulting in some sort of spaghetti routing like
App.AnimalsRoute = Ember.Route.extend({
events: {
goBackToThis: function() {
this.transitionTo('this');
},
goBackToThat: function() {
this.transitionTo('that');
},
goBackToSomeThingElse: function() {
this.transitionTo('someThingElse');
}
}
});
I would like to have 1 goback functionality for the whole router!
My initial solution result in something like the following: (look for all the goBack routes, and the reuse of the ebed routes)
App.Router.map(function (match) {
this.route('home', { path: '/' });
this.route('logout');
this.route('login');
this.resource('goBack', { path: '/goback' });
this.resource('ccpr', function () {
this.resource('goBack', { path: '/goback' });
this.resource('ccprPatients', { path: '/' }, function () {
this.route('search');
});
this.resource('ccprPatient', { path: '/:ccpr_patient_id' }, function () {
this.resource('goBack', { path: '/goback' });
this.resource('ccprPracticeSessions', { path: '/practicesessions' }, function () {
});
this.resource('ccprPracticeSession', { path: '/practicesessions/:ccpr_practicesession_id' }, function () {
this.route('info');
this.route('anamnese');
this.route('medication');
this.route('trainingModel', { path: '/trainingmodel' });
this.route('socialEvaluation', { path: '/socialevaluation' });
this.route('medicalFollowUp', { path: '/medicalfollowup' });
this.route('psychologicalEvaluation', { path: '/psychologicalevaluation' });
this.route('nutritionalAdvice', { path: '/nutritionaladvice' });
this.resource('goBack', { path: '/goback' });
this.resource('ebedMedication', { path: '/ebedmedication/:ebed_medication_id' }, function () {
});
this.resource('ebedLabResult', { path: '/ebedlabresult/:ebed_labresult_id' }, function () {
});
this.resource('ebedDietContact', { path: '/ebeddietcontact/:ebed_dietcontact_id' }, function () {
});
this.resource('ebedNutritionBmi', { path: '/ebednutritionbmi/:ebed_nutritionbmi_pkid' }, function () {
});
});
});
this.resource('ccprCardioArticles', { path: "/cardioarticles" });
this.resource('ccprCardiologists', { path: "/cardiologists" });
this.resource('ccprInfoSession', { path: "/infosession" });
this.resource('ccprPatientPresence', { path: "/patientpresence" });
this.resource('ccprPresenceOverview', { path: "/presenceoverview" });
this.resource('ccprNextNutritionalAdvices', { path: "/nextnutritionaladvices" });
});
this.resource('ebed', function () {
this.resource('goBack', { path: '/goback' });
this.resource('ebedMedications', { path: '/ebedmedications' }, function () {
});
this.resource('ebedMedication', { path: '/ebedmedication/:ebed_medication_id' }, function () {
});
this.resource('ebedLabResults', { path: '/ebedlabresults' }, function () {
});
this.resource('ebedLabResult', { path: '/ebedlabresult/:ebed_labresult_id' }, function () {
});
this.resource('ebedDietContacts', { path: '/ebeddietcontacts' }, function () {
});
this.resource('ebedDietContact', { path: '/ebeddietcontact/:ebed_dietcontact_id' }, function () {
});
this.resource('ebedNutritionBmis', { path: '/ebednutritionbmis' }, function () {
});
this.resource('ebedNutritionBmi', { path: '/ebednutritionbmi/:ebed_nutritionbmi_pkid' }, function () {
});
});
});
Isn't there a nicer way?

Updated JSFiddle example
You can do the same thing in the new router using the events property in the router to define actions. From the guide:
If the action is not found on the current controller, it will bubble
up to the current route handler. From there, it will bubble up to
parent route handlers until it reaches the application route.
In your example you need to define the goBack action in the parent of your animals.dog and animals.cat routes;
App.AnimalsRoute = Ember.Route.extend({
events: {
goBack: function() {
this.transitionTo('index');
}
} });
This can be called using the standard {{action}} helper from the template.
<a href='#' {{action goBack}}>Go Back</a>

Related

Is my router.js is correct?

Hi I am getting an error of UnrecognizedUrl when I am trying to access my route on my browser to dashboard/posts/id/comments. Below is my router.js I would like to ask if my router is wrong or can someone please tell me the right approach
this.route('dashboard', function() {
this.route('posts', function() {
this.route('show', { path: ':post_id' }, function() {
this.route('comments', { path: ':post_id/comments'}, function() { });
});
});
});
However if I put the {{outlet}} on my resource file app/pods/dashboard/posts/show/template.hbs it does show the content I put on my app/pods/dashboard/posts/show/comments/template.hbs when I changed my router.js to
this.route('dashboard', function() {
this.route('posts', function() {
this.route('show', { path: ':post_id' }, function() {
this.route('comments');
});
});
});
My goal is I want to show the content of app/pods/dashboard/posts/show/comments/template.hbs on a different page which in the browser url should be dashboard/posts/id/comments
It should be like
this.route('dashboard', function() {
this.route('routeA', function() {
this.route('childRouteA', { path: '/:childRouteA_id' }, function() {
this.route('childRouteAb');
});
});
});
Ex: dashboard/routeA/id/childRouteAb
If childRouteAb is a dynamic id then, it should be like
this.route('dashboard', function() {
this.route('routeA', function() {
this.route('childRouteA', { path: '/:childRouteA_id' }, function() {
this.route('childRouteAb', { path: '/:childRouteAb'});
});
});
});
Ex: dashboard/routeA/id/id2
If you need the url to specify the type of id before the id, you can do like this.
this.route('dashboard', function() {
this.route('routeA', function() {
this.route('childRouteA', { path: '/childRouteA/:childRouteA_id' }, function() {
this.route('childRouteB', { path: '/childRouteB/:childRouteB_id'});
});
});
});
Ex: dashboard/routeA/childRouteA/id1/childRouteB/id2

How to set nested route path same level as the parent route?

this.route('browse', { path: '/points' }, function() {
this.route('quiz', { path: '/quiz' });
this.route('learn', { path: '/learn' });
});
this.route('post', { path: '/post' }, function() {
this.route('star', { path: '/star' });
this.route('marked', { path: '/marked' });
});
The reason I want to do this is that I would like to share same base template between nested routes and I do not put all these into application template (otherwise I need to place so many condition block in it).
What I want to achive is
browse -> /points
browse.quiz -> /quiz
browse.learn -> /learn
post -> /posts
post.star -> /star
post.marked -> /marked
Try resetNamespace
this.route('browse', { path: '/points' }, function() {
this.route('quiz', { resetNamespace: true });
this.route('learn', { resetNamespace: true });
});

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.

Ember: object resolving of nested resources

I've recently started using Ember.js with Ember-CLI and I'm pretty excited.
But there are some things that are not clear for me.
Here is my router:
this.resource("authenticated", { path: '/' }, function() {
this.resource("contacts", function() {
this.resource("contact", { path: ':id' });
});
this.resource("chats", function() {
this.resource("chat", { path: ':id' });
});
this.resource("settings", function() {
this.resource("setting", { path: ':id' });
});
});
The question is - why after 2nd nesting 'resolver' starts finding objects outside of 'authenticated' resource?
For example
my-app/pods/chats/index/view
But expected
my-app/pods/authenticated/chats/index/view
Why is 'authenticated' missed ?
Your authenticated route is not applied in the url because you assigned it's url to the root: { path: '/'}.
You should either change the path to 'authenticated' or remove it all together:
this.resource("authenticated", function() {
...
});
Now, however, authenticated is only rendered when a user navigates to my-app/pods/authenticated. If you still want to render authenticated as index, you should prefix your nested resources:
this.resource("authenticated", { path: '/' }, function() {
this.resource("contacts", { path: '/authenticated/contacts' }, function() {
...
});
this.resource("chats", , { path: '/authenticated/chats' }, function() {
...
});
...
});
I hope this helped you.

Ember + Ember Data Route error handling issue

In soume routes in my app error action is never triggered and I can't figure out why. On some Routes error action works fine.
This is application route:
Simitu.ApplicationRoute = Ember.Route.extend({
init: function() {
this._super();
Simitu.AuthManager = Simitu.AuthManager.create();
},
model: function() {
if (Simitu.AuthManager.get('session.user'))
return this.store.find('admin', Simitu.AuthManager.get('session.user'));
},
actions: {
error: function(reason, transition) {
if (reason.status === 401) {
Simitu.AuthManager.reset();
this.transitionTo('login');
}
}
}
});
On this route Error is never triggered:
Simitu.PlacesIndexRoute = Ember.Route.extend({
model: function() {
var self = this;
// force adapter request
this.store.find('place');
return this.store.filter('place', function(record) {
// return just places that belongs to this client / application
return record.get('client_id') === self.modelFor('client');
});
},
actions: {
createNew: function() {
var place = this.store.createRecord('place');
// tree structure in places is not implemented yet
//parent = this.store.find('place', params.place_id);
place.set('client_id', this.modelFor('client'));
// open place
this.transitionTo('place', place);
},
error: function(error, transition) {
return true;
}
}
});
And on this Route everything works just fine:
Simitu.ClientsRoute = Ember.Route.extend({
model: function() {
return this.store.find('client');
},
actions: {
error: function() {
return true;
}
}
});
Have anybody some ide why?
The error action is fired on the resource, not an individual route.
http://emberjs.jsbin.com/cayidiwa/1/edit
This is how my router looks like. Maybe it breaks because of the nesting or filter logic in models. I fixed it in beforeModel hook in routes but still have not clue what is wrong with my first solution.
Simitu.Router.map(function () {
this.resource('login');
this.resource('clients');
this.resource('client', { path: 'clients/:client_id'}, function() {
this.resource('places', function() {
this.resource('place', { path: ':place_id' });
});
this.resource('placecategories',{ path: 'places-categories' }, function() {
this.route('new');
});
});
});
I move some of auth handling logic to beforeModel hook.
Simitu.AuthRoute = Ember.Route.extend({
beforeModel: function(transition) {
if (!Simitu.AuthManager.isAutenticated()) {
this.redirectToLogin(transition);
}
},
redirectToLogin: function(transition) {
this.transitionTo('login');
},
actions: {
error: function(reason, transition) {
if (reason.status === 401) {
Simitu.AuthManager.reset();
this.redirectToLogin(transoition);
}
}
}
});