How do I version a route in Ember properly? - ember.js

I have an application where I would like to namespace a specific route. But I'm seeing that Ember renders the ancestor route (which is similarly named).
Details
Ember 1.12.0
Routes
this.resource('campaign', { path: ':campaign_id' }, function() {
// some more routes
});
this.resource('campaign_v2', { path: 'v2/:campaign_id' }, function() {
// new routes
});
Link in campaign template
{{link-to "Check out V2!" "campaign_v2" classNames="btn btn-primary"}}
Test
Expect: When visiting campaign.index and I click on "Check out V2!", I expect to be taken to campaign_v2.index
Result: I am taken to campaign_v2.index but campaign also renders
Here is the result in Ember Inspector:
However, if I reload the route, I get:

Don't use the resource helper and instead use the route helper. Also, you might consider using a route namespace (instead of the _v2 suffix).
Routes
this.route('campaign', { path: ':campaign_id' }, function() {
// more routes
});
this.route('v2', function() {
this.route('campaign', { path: ':campaign_id' }, function() {
});
You can then refer to the v1 and v2 route via: campaign and v2.campaign respectively.

Related

What is the difference between route and path in EmberJs

What is the difference between route and path in EmberJs
Router.map(function () {
this.route('about');
this.route('contact', { path: '/getting-in-touch' });
});
The first argument to route is the name of the route. It's used to find the right files to load app/routes/about.js and to provide links <LinkTo #route="about">About</LinkTo>. If you provide a path option it is used to create the URL you see in the location bar for the browser.
From the ember guides
You can leave off the path if it is the same as the route name.
For your case the following are equivalent:
Router.map(function () {
this.route('about', { path: '/about' });
this.route('contact', { path: '/getting-in-touch' });
});
Router.map(function () {
this.route('about');
this.route('contact', { path: '/getting-in-touch' });
});
Will results in Ember knowing how to load URLs for https://yoursite.com/about and https://yoursite.com/getting-in-touch
And for <LinkTo #route="contact">Contact Us</LinkTo> to create a link with HTML like Contact Us

Add a parent route in ember for existing routes

Here is my problem,
assume I am having an ember app with following ember route configuration:
Router.map(function() {
this.route('todos', function() {
this.route('new');
this.route('view', {
path: "/:id"
});
});
this.route('articles', function() {
this.route('view', {
path: "/:id"
});
this.route('new');
});
});
Now i want to add the add the prefix for each route based on some user information i would be fetching.
For eg:
Below are the two user information
dev = {
id: 1,
workspace: 'DEV'
}
qa = {
id: 2,
workspace:'TEST'
}
once the dev is landing in the app, route must be like:
todos:
/DEV/todos/new
and same for the other users.
once the qa is landing in the page, route must be like:
/TEST/todos/new
to solve this i know we generate the parent route and add all the other route as child, need to change the file structure for this case.
Here is Ember :
ember-cli: 2.13.3,
ember-data: 2.18.5
This is straight forward in Ember.js using the router's path as URL paths can be customized easily.
For your case, the todos route should have a dynamic segment (say, workplace) and hence, the router entry will be like:
Router.map(function() {
this.route('todos', { path: '/:workplace/todos' }, function() {
this.route('new');
...
});
});
And if you are transitioning to new todo page using this.transitionTo('todos.new', 'TEST'), then URL will be updated as TEST/todos/new.
This twiddle has a tiny demo. Hope that helps :)

How to namespace an ember route in Ember 1.11.0

My understanding is that Ember 1.11.0 deprecated resource in a router in favor of only using route. Per what I've read, the difference between the two was that a resource created a namespace. See: What is the difference between a route and resource in New Router API?
So the question is how do I namespace a route so that, in the example below, my comments Route, Controller, and View are not prefixed with 'Posts'?
App.Router.map(function() {
this.route("posts", { path: "/" }, function() {
this.route("new", { path: "/new" });
this.route("comments", { path: "/comments" }, function() {
this.route("new", { path: "/new" });
});
});
});
Try passing resetNamespace: true to the route like
this.route("comments", { path: "/comments", resetNamespace: true }, function() {
this.route("new", { path: "/new" });
});
You can use the resetNamespace option for a route, something like this:
this.route('posts', {}, function() {
this.route('comments', {resetNamespace: true});
});
Currently, there's no way of doing that using the public API without using this.resource, which is officially deprecated and slated for removal in Ember 2.0. Using resetNamespace is not officially supported as it is a private API so, technically, it may be removed at any time without warning.
The official solution to this problem is to refactor your application to accept that the Comments Routes and Templates are under Posts.

EmberJS-Rendering templates for nested resources

My Ember router looks similar to below.
App.Router.map(function() {
this.resource('projects', function () {
this.resource('listings', { path: '/:project_id/listings' }, function() {
this.route('listing', { path: '/:listing_id' });
});
});
});
I have 2 templates (projects, listings). The projects template has a {{#link-to}} helper that adds an anchor to the listings resource. The projects template is working fine. The {{#link-to}} helper also seems to generate the url correctly (~ /projects/2/listings).
Now the listings are rendered correctly but they are rendered inside the projects template. I assume this is because the resources are nested. So I removed the nesting and made both projects and listings as their own resources.
App.Router.map(function() {
this.resource('projects');
this.resource('listings', { path: 'projects/:project_id/listings' }, function() {
this.route('listing', { path: '/:listing_id' });
});
});
The problem is when the route transitions to listings, the listings template is not rendered. It's just blank. The below fiddle demonstrates the issue.
Fiddle: http://jsfiddle.net/harshavarma/aqHnt/3/
To do what you want, structure your routes in the same way you started with
App.Router.map(function() {
this.resource('projects', function () {
this.resource('listings', { path: '/:project_id/listings' }, function() {
this.route('listing', { path: '/:listing_id' });
});
});
});
Then, the projects template should only be {{outlet}}. If there is content that you want to render only when you navigate to /projects, but not when you navigate deeper, put that content in a projects/index template (or whatever that template is called based on your naming conventions) and setup any necessary router and controller stuff on ProjectsIndexRoute and ProjectsIndexController. Now your listings template will only be nested inside projects which is just an outlet, and you won't see any of the projects/index content when viewing listings.
http://emberjs.com/guides/routing/defining-your-routes/#toc_resources

Ember router naming conventions

I have a need for deep nesting some routes in ember, I have something like this.
this.resource('wizards', {
path: '/wizards'
}, function() {
this.resource('wizards.google', {
path: '/google'
}, function() {
this.resource('wizards.google.register', {
path: '/register'
}, function() {
this.route('step1');
this.route('step2');
this.route('step3');
this.route('summary');
});
});
});
What I was expecting was as structure like this:
url /wizards/google/register/step1
route name wizards.google.register.step1
route Wizards.Google.Register.Step1Route
Controller Wizards.Google.Register.Step1Controller
template wizards/google/register/step1
but I got this:
url /wizards/google/register/step1 //as expected
route name wizards.google.register.step1 //as expected
route WizardsGoogle.Register.Step1Route
Controller WizardsGoogle.Register.Step1Controller
template wizards/google.register.step1
What I don't get is when does ember stop using capitalization (WizardsGoogle) and start using namespaces (WizardsGoogle.Register). The seemingly inconsistency confuses me. I would have expected either of them.
I met the same things with deep nested resources. Although I didn't know how this happens, what I can tell is that you can always use CapitalizedNestedRoute without namespace, and Ember can recognize it. Although in Ember Inspector it displays "WizardsGoogle.Register.Step1Route".
In your example I defined such route:
App = Em.Application.create();
App.Router.map(function() {
this.resource('wizards', function() {
this.resource('wizards.google', function() {
this.resource('wizards.google.register', function() {
this.route('step1');
this.route('step2');
this.route('step3');
});
});
});
});
App.IndexRoute = Em.Route.extend({
beforeModel: function() {
// Transition to step1 route
this.transitionTo('wizards.google.register.step1');
}
});
App.WizardsGoogleRegisterStep1Route = Em.Route.extend({
model: function() {
// You can see this alert when you enter index page.
alert('a');
}
});
In this example the app will transition to WizardsGoogleRegisterStep1Route with no problem. And if you use container to find route like this:
App.__container__.lookup('route:wizards.google.register.step1').constructor
It will also display App.WizardsGoogleRegisterStep1Route. It's the same as Ember Guide describes. http://emberjs.com/guides/routing/defining-your-routes/#toc_nested-resources And Ember Guide doesn't introduce namespace route.
So I think it's better to according to what Ember Guide suggests (always use CapitalizedNestedRoute). And in my opinion it's easier to define CapitalizedNestedRoute than nested.namespace.route.
Finally, if you really want to use namespace route/controller/template, you can have a look at Ember.DefaultResolver. Check the API to learn how to extend it so container can lookup modules by your own rules.
Routes are "namespaced" inside resources. And resources uses what you call capitalization, where they sort of define a namespace (for routes to use).
So this set of routes:
App.Router.map(function() {
this.resource('posts', function() {
this.route('new');
this.route('old');
this.route('edit');
this.route('whatever');
});
});
Would result in routes with the following name:
PostsRoute
PostsNewRoute
PostsOldRoute
PostsEditRoute
PostsWhateverRoute
Whereas, the following set of routes:
App.Router.map(function() {
this.resource('posts', function() {
this.resource('photos');
this.resource('comments');
this.resource('likes');
this.resource('teets');
});
});
Would result in route with the following names:
PostsRoute
PhotosRoute
CommentsRoute
LikesRoute
TeetsRoute
Also note, that resources within resources don't get "namespaced" to the "parent" resource, so you'll always ever have the form:
{CapitalizedResourceName}Route // for resources
{CapitalizedParentResourceName}{RouteName}Route // for routes
I hope this helps you!