Simple ember routing - how to define multiple routes? - ember.js

Ok guys- It really shouldn't get simpler than this. I defined a route named about and added a linkTo about in my template, ran it through the outlet and ember works as expected.
I then added another route called foobars, did the same thing with it and get an uncaught error:
Uncaught Error: assertion failed: The attempt to linkTo route 'foobars' failed. The router did not find 'foobars' in its possible routes: 'about', 'index'
Here's my ember
App = Ember.Application.create()
App.Router.map(function(){
this.resource('about');
this.resource('foobars');
});
My drop dead simple html
<body>
<h1>ember</h1>
<script type="text/x-handlebars">
<h2>application template</h2>
<a>{{#linkTo 'about'}} about {{/linkTo}}</a>
<a>{{#linkTo 'foobars'}} foobars {{/linkTo}}</a>
{{ outlet }}
</script>
<script type="text/x-handlebars" id="about">
<h2>about template</h2>
</script>
<script type="text/x-handlebars" id="foobars">
<h2>foobars template</h2>
</script>
Like I said, it works with the about template, so I know my config is ok. I've also tried adding them separately, like so:
App.Router.map(function(){
this.resource('about');
});
App.Router.map(function(){
this.resource('foobars');
});
I would expect that defining two routes would not be that much different than defining one route, but I am not seeming to understand something. Could someone point out the error of my understanding? Thanks!

I think you just didn't save your file before reloading your page. I tried your example and it worked well for me.
However when I comment out the foobars route:
App = Ember.Application.create();
App.Router.map(function() {
this.resource("about");
//this.resource("foobars");
});
I got the same exact error in my console:
Error: assertion failed: The attempt to linkTo route 'foobars' failed. The router did not find 'foobars' in its possible routes: 'about', 'index'

You need to define the routes in the form:
App.FoobarsRoute = Ember.Route.extend({
model: function() {
return App.Foobars.find();
}
});
This will typically go in its own file: /routes/foobars_route.js

Related

Uncaught TypeError: Cannot call method 'connectOutlet' of undefined

I'm getting an undefined parent View for my loading route handler -- but only when a specific page is navigated to first in my application.
http://www.sentinel21.com/#/posts
If you visit the about page first or the root, the loading handler seems to load properly. I'm not sure what I'm doing to cause the loading route to render improperly in that case.
Here's the loading route.
App.LoadingRoute = Ember.Route.extend({
renderTemplate: function(){
this.render('loading', {
outlet: "loading",
into: "application"
});
}
});
My application template has this code.
<div class="content">
<div class="column row"></div>
{{outlet "loading"}}
{{outlet}}
</div>
All the code is available on github, and that's probably the easiest place to see the templates, which are precompiled.
I had this same problem, and it was because my app template was named "app.handlebars" but should have been called "application.handlebars". Once I changed it, the outlet was found and everything worked as expected.

Emberjs 1.0 named templates: Cannot call method 'connectOutlet' of undefined

Named templates seem straightforward enough on paper, but for the life of me I can't make it work with emberjs 1.0, even with a trimmed down example (See jsbin here: http://jsbin.com/uNUQUhi/1/).
The handlebar templates:
<script type='text/x-handlebars' id='index'>
<div>{{outlet test}}</div>
</script>
<script type='text/x-handlebars' data-template-name='test'>
<h1>A test</h1>
</script>
...and the javascript:
App = Ember.Application.create() ;
App.IndexRoute = Ember.Route.extend({
renderTemplate: function(controller, model) {
this.render('test', {
outlet:'test',
into: 'index'
});
}
});
I must be missing something? But what? I couldn't find a working example of a named outlet (at least not one that worked with v.1.0)
The 'index' template would be the 'normal' template that would be rendered by IndexRoute. Since you're telling it to render the 'test' instead, the 'index' template is never rendered, and as a result Ember can't find your named outlet. If you rename the 'index' template to 'application', and the render into : 'application' everything works out.
http://jsbin.com/oLULeRo/1/edit

Ember rendering only the root template

I am trying to set up an ember app, but am recieving some strange behavior. I have two routes set up: "welcome", which is mapped to "/"; and "features", which is mapped to "/features". When navigating to "/", the welcome template correctly renders. But, when I navigate to "/features", it still renders the welcome template.
This jsbin actually works correctly: http://jsbin.com/OSoFeYe/1 , but the code below, which is from my app, does not.
App.Router.map(function() {
this.route("welcome", {path: "/"});
this.resource("features", {path: "/features"}, function() {
this.route("new");
});
});
App.FeaturesIndexRoute = Ember.Route.extend({
});
<body>
<div class="container">
<script type="text/x-handlebars">
<h1>rendered application template</h1>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="features">
<h2>Render features</h2>
<h6>Done features template</h6>
</script>
<script type="text/x-handlebars" data-template-name="welcome">
<h2>Render welcome</h2>
</script>
</div>
</body>
Any insight to this issue would be appreciated.
Add the following to your js file and you won't need the hash anymore.
App.Router.reopen({
location: 'history'
});
Take the code from your jsbin and stick it in your app, you probably have a typo or some block of code where you shouldn't. I edited your "welcome" template to have the following link in the jsbin and it worked perfectly for me.
<script type="text/x-handlebars" data-template-name="welcome">
<h2>rendering welcome template</h2>
{{#linkTo "features"}}features{{/linkTo}}
</script>
In the welcome link it has a link that says "features" directly below the text "rendering welcome template". And when you click the link it says "rendering features template".
Ok, I think I see the issue here, and it's based on my misunderstanding of how ember routes work. I need to include a hash in my url. So my features url is /#/features, not /features.

ember.js template not rendered

While it doesn't become simpler than this: fiddle I can't get the template to be rendered. I'm obviously missing something simple but have been starring at this for hours now. Can somebody spot the error?
When debugging in chrome I can see that the View is entered as well as the controller, but the template doesn't seem to come to life. I have several other ember tests running on my laptop that render just fine.
<script type="text/x-handlebars" data-template-name="index">
<h1>Application</h1>
<p>Your content here.</p>
{{outlet}}
</script>
Albumartist = Ember.Application.create();
Albumartist.Router.map(function(match) {
this.route('index', {path: '/'});
});
Albumartist.IndexView = Ember.View.extend({
});
Albumartist.IndexRoute = Ember.Route.extend({
});
Albumartist.IndexController = Ember.Controller.extend({
renderTemplate: function(controller, model){
console.log('hi');
}
});
The problem is simple: You chose Ember as a Framework didn't include jQuery, which is necessary for Ember to run. I've updated the Fiddle to include Ember and Handlebars as a resource and jQuery as a Framework.
Also, since Router v2.1 you don't have to pass the match argument to the router:
Albumartist.Router.map(function() { // no match argument needed anymore
this.route('index', {path: '/'});
});
If I am not mistaken, you need to wrap your code in <script> tags which appear to be missing. This could possibly by a typo when copying your code over to this site though.

ember.js routers and connectOutlets

I'm trying to use an already instantiated controller in my ember route.
Is it not normal to ever have instantiated a controller and want to use that in a route? I know that if I the application instantiate a controller for me, I can then to router.get("myController") but that won't access one that I had instantiated myself.
How do I get the piece of code at the bottom of my router to work?
HTML
<script type="text/x-handlebars" data-template-name="application">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="instanced">
<h1>Hello from instanced template</h1>
{{showinstancedvalue}}<hr>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="foobar">
<h1>hello from foobar</h1>
{{foobarvalue}}
</script>
Javascript
var App = Ember.Application.create();
// application view and controller
App.ApplicationView = Ember.View.extend({
templateName: 'application',
});
App.ApplicationController = Ember.Controller.extend();
// foobar controller and view
App.FoobarController = Ember.Controller.extend({
foobarvalue: "working"
});
App.FoobarView = Ember.View.extend({
templateName: 'foobar'
});
// instantiated controller and view
App.InstancedController = Ember.Controller.extend({});
App.instancedController = App.InstancedController.create({
myvar: "a value from an instantiated controller"
});
App.InstancedView = Ember.View.extend({
templateName: 'instanced',
});
App.instancedView = App.InstancedView.create({
showinstancedvalueBinding: 'App.instancedController.myvar'
});
App.instancedView.append();
App.router = Ember.Router.create({
enableLogging: true,
root: Ember.Route.extend({
index: Ember.Route.extend({
route: '/',
redirectsTo: 'works'
}),
works: Ember.Route.extend({
route: '/works',
connectOutlets: function(router) {
router.get('applicationController').connectOutlet('foobar');
}
}),
broken: Ember.Route.extend({
route: '/broken',
connectOutlets: function(router) {
// no error in console, but foobar doesn't appear
// router.get('instancedController').connectOutlet('foobar');
// *** this one was my best guess as to what I thought would work ***
// no error in console, but foobar doesn't appear
// App.instancedController.connectOutlet('App.Foobar');
// Uncaught Error: assertion failed: The name you supplied foobar did not resolve to a view FoobarView
// App.instancedController.connectOutlet('foobar');
}
}),
})
});
App.initialize(App.router);​
Take a look at the connectOutlet definition, it includes a basic documentation as a comment so you can have a better understanding of how it's supposed to or and to be used.
Basically, you should really connect it to the applicationController, since the {{outlet}} sits on the ApplicationView template. In this scenario, the framework will find a view and controller that should be used in that state (in your case FoobarView and foobarController since it's specified with the argument 'foobar') and add to a collection (named controllers) inside the applicationController. If you try to connect directly to your instance of foobarController, it won't find a outlet on its view (which at that moment shouldn't be instantiated, I believe) AND you'd be saying to that controller "hey, find yourself, then connect yourself to you" kind of thing.
This could work if you had an outlet inside the foobar view template and you'd connect this outlet to something other than foobar (as a child state/route). So you should read more about the outlets and named outlets.
Additionally, I strongly recommend these links:
Router Primer - This article is about two weeks fresh, and it's apparently the best there is right now, make sure you read this one!
Ember.js Routing - the Director’s Cut - Step-by-Step post about the Router, make sure you read this one too.
Outlets - This is a bit old but is being mantained
JSFiddle Sample 1 - Sample Fiddle with routing you can use as reference
JSFiddle Sample 2 - Sample Fiddle with routing you can use as reference (this is newer than previous)
You should try to elaborate on your requirements. This makes no sense from my point of view.
broken: Ember.Route.extend({
route: '/broken',
connectOutlets: function(router) {
App.foobarController.connectOutlet('foobar');
}
}),
This code just can't work, since you are invoking connectOutlet on your fooBarController. So it searches for {{outlet}} in the assigend view. But in the template named foobar you do not not have a {{outlet}} specified. And even if you fix that, it makes just no sense, since this line would try to connect an outlet with a new instance of Foobar View. So you basically have the FooBarView of your FooBarController and inside its view, you try to connect a outlet again with a new instance of FooBarView??
So without explanation of requirements this question cannot be answered.