Ember.js nested routes with shared models - ember.js

I have this on my router.js:
this.resource('campaigns', {path:'/campaigns'}, function() {
this.route('index', {path: '/'});
this.route('group', {path: '/*campaign_group_id'});
});
So it's a route called campaigns, and 2 nested routes: index and group.
When the browser is on the group route, I need to access the model from group route, on the campaigns route/controller.
But I can't access it. I always get the model that it's on campaigns.js route.

If you set the model from the campaign.group route on its controller, you should be able to use controllerFor to from the campaigns route, something like
// routes/campaigns.js
this.controllerFor('campaigns.group').get('your-prop')
You could also send an action from your group route and handle it in the parent campaigns route, sending along the model. This is perhaps more idiomatic with Ember 2.0 conventions.
Btw if you're using Ember CLI (which you should be) you should try getting rid of this.resource and putting all your routes/templates/controllers in pods.

Related

How to render nested route in new page Ember js?

I currently trying use LinkTo to render another nested route by using {{outlet}} tag to another new page.
I have a forum route and nested forum details route
In the forum template:
<LinkTo #route="main.forum.forum-details" #model={{post}}>{{post.title}}</LinkTo>
{{outlet}}
As the image above. The nested route will be render at the bottom instead of to the new page. How am i going to render it to new page? I was thinking LinkTo will actually link it to the new page right? And the forum details should be render at the {{outlet}} tag, so where should I place the {{outlet}} tag in order to let it render to new page?
You problem is that you need to understand nested routes.
If your route is main.forum.forum-details this means your router looks like this:
this.route('main', function() {
this.route('forum', function() {
this.route('forum-details');
});
});
So the forum route is a parent route of the forum-details route.
And its important to understand that parent routes are always visible when visiting a child route.
So for the main.forum.forum-details ember will render your application route and inside its {{outlet}} it will render the forum route and inside this {{outlet}} it will render the forum-details route.
So if you want either the forum or the forum-details route you can restructure your routes:
this.route('main', function() {
this.route('forum');
this.route('forum-details');
});
or you can move what you currently have in your forum route to your forum.index route. If a route has subroutes and none of the subroutes is active there will always be an index route active that you can use.

Ember router can transition to but not handle a url

Using Ember 2.1.0 with EmberData, I'm making a small blogging app. It has two routes
Router.map(function(){
this.route("posts", {path: "/"});
this.route("post", {path: '/:seo_friendly_link'});
}
The seo_friendly_link looks like this
/2015/10/28/my-blog-post-title/
In the index route, I display a list of posts with links to each post. If I click a link, the Ember app will transition to the post that I clicked on showing the seo-friendly-url in the browser. I emphasize transitionto-- the routing goes through that method in Ember router. Everything works fine up to here.
The problem:
However, if I drop/type that same url into the browser (rather than transition to it from a link on the homepage), I get an UnrecognizedURLError (before the model or even the beforeModel hook are called for the post). If I drop the url into the browser, the routing goes through the handleURL method on Ember Router, which doesn't happen if I click a link from the homepage. So my Ember app can transition to my seo_friendly_link, but not handle that url.
I'm not sure why.
Question: How can I create a route to recognize that link?
Code
There is a property on the Post model called
seo_friendly_link: DS.attr('string')
In /routes/post, I call the serialize method to create that parameter from the model property
serialize: function(model, params){
seo_friendly_link: model.get("seo_friendly_link");
}
Your dynamic segment /:seo_friendly_link doesn't match slashes, e.g. it will match /2015 but not /2015/10.
To match the whole path including slashes, change the : to an *:
Router.map(function(){
this.route("posts", {path: "/"});
this.route("post", {path: '/*seo_friendly_link'});
}

Ember js - want to style outer route based on nested route

I am learning Ember, and I have an app that has nested routes. The outer route renders an index of products that acts as a sidebar, and the inner route renders the selected product.
So I have a setup like this in my coffeescript router:
#resource 'products', ->
#resource 'product'
And then I have a template like so for product_types.js.emblem:
each product in controller
.product<NEED_SOMETHING_HERE>
I want NEED_SOMETHING_HERE to give me an extra attribute that will allow me to add a style to the product which will be rendered in the inner route. A class "active", or something similar, is the convention I would use elsewhere. What is the Ember way to do this?
Ember actually does this automatically with the link-to helper!
Ember adds an "active" class when the link matches the current route
http://emberjs.com/guides/templates/links/#toc_the-code-link-to-code-helper

In Ember, how to keep parent route's model consistent with child routes?

Here are my routes:
this.resource('kb_obj', {path: '/kb/:data_type'}, function() {
this.resource('kb_obj_show', {path: '/:id'}, function() {
this.route('with_breadcrumb', {path: '/:breadcrumb'});
});
this.resource('kb_filtered_page', {path: '/:filter_params/page/:page_id'}, function() {
this.route('index', {path: '/'});
});
});
As you can see, the KbObjRoute's main job is to store the current data type.
My problem is that when someone clicks a link such as this:
{{#linkTo 'kb_obj_show.with_breadcrumb' this this}}{{name}}{{/linkTo}}
The model or setupController methods are not fired on the KbObjRoute, so it never gets to update its data type and anything that depends on that info (e.g. the main nav links) don't get updated.
I can't see how to notify the parent route of what's going on with its children.
Am I missing something?
Thanks!
I think there might be two misconceptions here
your sub-routes build on the parent route but don't modify it (more
below) perhaps there is a mismatch with what you are trying to achieve
and the URL structure
the model method won't be called for a linkTo (because the
linkTo is supplying the model). if someone drops directly into the
route they will be called
The URL /kb/image might load a bunch of images as the model. /kb/image/123 is one of those images. Changing 123's data_type isn't going to bubble up and change the dynamic segment.
That being said, routes and controllers can depend on eachother in a few ways.
With routes, you can use the modelFor method, in your case I think it would be:
this.modelFor('kb_obj')
With controllers you would use the needs array. So if you wanted to get a model or property from another controller you can do that:
App.SubController = Ember.ObjectController.extend({
needs: "otherController",
linkedProperty: Ember.computed.alias("controllers.otherController.model.itsProperty")
});

Ember.js - How do I insert a controller?

So my understanding from the Ember docs is that the pattern for views/controllers/models is as follows:
[view] <- [controller] <- [model]
(with views consuming controllers consuming models)
In my previous experience using Ember, I'd set up a view to consume a model, like so:
{{#with blogpost}}
{{#view MyApp.BlogPostView contentBinding="this"}}
<h1>{{title}}</h1>
<p>{{content}}</p>
{{/view}}
{{/with}}
Now say I create a controller:
MyApp.BlogPostController = Ember.BlogPostController.extend()
Where do I initialize this controller?
Looking at the Ember docs, it seems like this happens automatically if the controller is associated with a route, but what if I just want an ad-hoc controller which ties together a view and a model? This could be for an arbitrary component on my page.
Am I responsible for instanciating the controller? Should I use some kind of controllerBinding attribute? Will it be instantiated automatically with my model, or with my view?
Any advice appreciated; I'm comfortable with the model/view pattern in Ember, but I'm having some difficulty working out where controllers fit in.
Looking at the Ember docs, it seems like this happens automatically if the controller is associated with a route
This is correct, a controller associated with a route will be automatically instantiated by ember when needed.
but what if I just want an ad-hoc controller which ties together a view and a model? This could be for an arbitrary component on my page. Am I responsible for instanciating the controller? Should I use some kind of controllerBinding attribute? Will it be instantiated automatically with my model, or with my view?
There are different way's to get your arbitrary controller instantiated automatically by ember without the needs of doing it yourself.
For the examples, let's assume you have a controller which is not associated with any routes called LonelyController,
App.LonelyController = Ember.ArrayController.extend({
content: ['foo', 'bar', 'baz']
});
Approach 1
Let's assume you have a route and you hook into setupController, if you try here to request you LonelyController with this.controllerFor('lonely'); this will make ember instantiate it for you:
App.IndexRoute = Ember.Route.extend({
setupController: function(controller, model) {
this.controllerFor('lonely').get('content');
// the above line will retrive successfully
// your `LonelyController`'s `content` property
}
});
Approach 2
Another possible way to get your LonelyController automatically instantiated by ember would be by defining a dependence with the needs API in another controller:
App.IndexController = Ember.ObjectController.extend({
needs: 'lonely',
someAction: function() {
this.get('controllers.lonely').get('content');
// the above line will retrive successfully
// your `LonelyController`'s `content` property
}
});
Using the needs API you could also doing something like this:
App.IndexController = Ember.ObjectController.extend({
needs: 'lonely',
lonelysContentBinding: 'controllers.lonely.content',
someAction: function() {
this.get('lonelysContent');
// the above line will retrive successfully
// your `LonelyController`'s `content` property
}
});
There are also some other combinations of the mentioned methods to get your LonelyController automatically instantiated, but I guess this should be more clear by now.
One last tip: to get a clue of what ember creates automatically under the hood you could also enable the generation logging to observe this in your console, which is very helpful, by doing:
var App = Ember.Application.create({
LOG_ACTIVE_GENERATION: true
});
Hope it helps.