Linking between templates - ember.js

I don't understand templates and routes.
My code:
<script type="text/x-handlebars" data-template-name="application">
Hello
<nav>
{{#link-to 'index'}}Index{{/link-to}}
{{#link-to 'about'}}About{{/link-to}}
{{#link-to 'contact'}}Contact{{/link-to}}
</nav>
</script>
<script type="text/x-handlebars" data-template-name="about">
about
</script>
<script type="text/x-handlebars" data-template-name="contact">
favorites
</script>
and router.js:
App.Router.map(function () {
this.route("index", { path: "/" });
this.route("about", { path: "/about" });
this.route("contact", { path: "/contact" });
});
What is wrong? Output is blank page. There appeared a problem when I had inserted {{#link-to}} code.
I did that by an emberjs guide.

You need to define a place where your templates you are linking to should display, such a placeholder is called an outlet, so simply add {{outlet}} where in you application template you want your routes corresponding templates to be rendered into:
Also note, the linkTo helper is called linkTo and not link-to depending on the ember release you are using:
<script type="text/x-handlebars" data-template-name="application">
Hello
<nav>
{{#linkTo 'index'}}Index{{/linkTo}}
{{#linkTo 'about'}}About{{/linkTo}}
{{#linkTo 'contact'}}Contact{{/linkTo}}
</nav>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="about">
about
</script>
<script type="text/x-handlebars" data-template-name="contact">
favorites
</script>
Working jsbin.
Hope it helps.

Related

How can I assign a common template for ember components

I have several components and each of them have a template all the same, how can I assign a common template for ember components?
To have common templates between components i would probably do one of the following,
Inherit one component from the other, or from a base one to extend the layoutName property
example1: http://emberjs.jsbin.com/jewohekiwu/1/edit?html,js
Use a common partial helper
example2: http://emberjs.jsbin.com/helefevome/1/edit?html,js
also an article with inheritance no layoutName property and a common partial http://blog.yanted.com/2014/01/17/inheritance-with-ember-js-components/
example1
hbs
<script type="text/x-handlebars" data-template-name="index">
{{my-comp1 testProp="lala"}}
<br/>
{{!other-name-for-comp2 testProp="lolo2"}}
{{my-comp2 testProp="lolo"}}
</script>
<script type="text/x-handlebars" data-template-name="components/my-comp1">
comp1 - testProp:{{testProp}}
</script>
js
App.MyComp1Component = Em.Component.extend({
layoutName:"components/my-comp1",
test:function(){console.log("comp1");console.log(this.get("testProp"));}.on("init")
});
App.MyComp2Component = App.MyComp1Component.extend({
test:function(){console.log("comp2");console.log(this.get("testProp"));}.on("init")
});
//Em.Handlebars.helper("other-name-for-comp2", App.MyComp2Component);
example2
hbs
<script type="text/x-handlebars" data-template-name="index">
{{my-comp1 testProp="lala"}}
<br/>
{{my-comp2 testProp="lolo"}}
</script>
<script type="text/x-handlebars" data-template-name="components/my-comp1">
{{partial "_commonTemplate"}}
</script>
<script type="text/x-handlebars" data-template-name="components/my-comp2">
{{partial "_commonTemplate"}}
</script>
<script type="text/x-handlebars" data-template-name="_commonTemplate">
comp1 - testProp:{{testProp}}
</script>
js
App.MyComp1Component = Em.Component.extend({
test:function(){console.log("comp1");console.log(this.get("testProp"));}.on("init")
});
App.MyComp2Component = Em.Component.extend({
test:function(){console.log("comp2");console.log(this.get("testProp"));}.on("init")
});

How to write my Ember router to achieve desired interface?

I've been playing with this for some time, and maybe it comes down to me not understanding how Ember (and/or ember-cli) treats routes and resources differently, but I'm trying to achieve an interface like this and having trouble with what my router and file structure should be for ember-cli. I've read the Ember docs through numerous times, but it's still not all clicking for me.
Desired interface
It mostly works, but when viewing /projects I don't see the logo, and when viewing /project/1/details[team | budget] I don't see my navigation, which is in my project.hbs file.
router.js
Router.map(function() {
this.route('projects');
this.resource('project', { path: 'project/:project_id' }, function() {
this.route('details');
this.route('team');
this.route('milestones');
this.route('budget');
});
});
File structure
App/
routes/
index.js
projects.js
project.js
templates/
application.hbs
index.hbs
projects.hbs
project/
index.hbs
budget.hbs
details.hbs
team.hbs
javascript
App = Ember.Application.create();
App.Router.map(function() {
this.route('projects');
this.resource('project', {path: 'projects/:id'}, function () {
this.route('details');
this.route('team');
this.route('milestones');
this.route('budget');
});
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return ['red', 'yellow', 'blue'];
}
});
App.ProjectsRoute = Ember.Route.extend({
model: function() {
return [
Ember.Object.create({id: 1, name: "John"}),
Ember.Object.create({id: 2, name: "Bob"})
];
}
});
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/normalize/2.1.0/normalize.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.3.0.js"></script>
<script src="http://builds.emberjs.com/tags/v1.7.0/ember.js"></script>
</head>
<body>
<script type="text/x-handlebars">
{{#link-to 'index'}}<h2>Welcome to Ember.js</h2>
Logo<br/><br/>
{{/link-to}}
{{#link-to 'projects'}}Projects{{/link-to}}
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
<div class='index'>
<ul>
{{#each item in model}}
<li>{{item}}</li>
{{/each}}
</ul>
</div>
</script>
<script type="text/x-handlebars" data-template-name="projects">
<div class='projects'>
<h3>Projects</h3>
{{#each}}
<li>{{#link-to 'project' this}}{{name}}{{/link-to}}</li>
{{/each}}
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="project">
<div class='project'>
<h4>{{name}}</h4>
<ul>
<li>{{#link-to 'project.details'}}Details{{/link-to}}</li>
<li>{{#link-to 'project.team'}}Team{{/link-to}}</li>
<li>{{#link-to 'project.milestones'}}Milestones{{/link-to}}</li>
<li>{{#link-to 'project.budget'}}Budget{{/link-to}}</li>
</ul>
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="project/details">
Some deets
</script>
<script type="text/x-handlebars" data-template-name="project/team">
the team
</script>
<script type="text/x-handlebars" data-template-name="project/milestones">
milestones
</script>
<script type="text/x-handlebars" data-template-name="project/budget">
budget
</script>
</body>
</html>
http://emberjs.jsbin.com/kovuxo/1#/

How to render template other than application.hbs in EmberJS?

In EmberJS, the main template file is the application.hbs. Any template rendered from the routes goes the the {{outlet}} of this main template file.
Now, I have another main template file, say print.hbs wherein the template design is very different from the application.hbs. How do I do this?
In the router file, I have:
App.Router.map(function() {
this.resource('print', function() {
this.route('display1');
this.route('display2');
});
this.route('dashboard', {path: '/'});
this.route('anything');
});
The routes dashboard and anything uses the application.hbs.
What should I do to use print.hbs on the print route? Please help.
You can't easily change application template. Ember doesn't listen on templateName property changes and responds poorly when you try to re-render the template yourself.
A nice way to do this would be to use different partials within your application template, based on whether you are in the 'screen' or 'print' mode.
<script type="text/x-handlebars">
{{#if isPrint}}
{{partial "application-print"}}
{{else}}
{{partial "application-normal"}}
{{/if}}
</script>
<script type="text/x-handlebars" data-template-name="application-normal">
<div id="app-normal">
<h2>Normal template</h2>
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="application-print">
<div id="app-print">
<h2>Print template</h2>
{{outlet}}
</div>
</script>
App.ApplicationController = Ember.Controller.extend({
isPrint: false,
currentPathChange: function () {
var currentPath = this.get("currentPath");
var isPrint = currentPath ? currentPath.indexOf("print") === 0 : false;
this.set("isPrint", isPrint);
}.observes('currentPath').on("init")
});
This JSBin will demonstrate why this, unfortunately, doesn't work either. According to this bug report, Ember's handlebars gets confused when there are multiple outlet directives in the same page, even if they are in different #if scopes.
Until this gets fixed, I propose the following, slightly modified, solution.
Application template is empty. One template each for normal and print section.
<script type="text/x-handlebars">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="normal">
<div id="app-normal">
<h2>Normal template</h2>
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="print">
<div id="app-print">
<h2>Print template</h2>
{{outlet}}
</div>
</script>
In router, everything goes into normal and print resources. Normal resources are placed at /, so that all the links remain the same. No need for special coding in ApplicationController.
App.Router.map(function() {
this.resource("print", function () {
this.route("a");
this.route("b");
});
this.resource("normal", {path: "/"}, function () {
this.route("a");
this.route("b");
});
});
Working jsbin here.

Ember.js template rendering

I'm possibly reading the docs wrong. Can someone please check out my gist and tell me why the invoices/index template is not rendering?
When I read the ember.js docs it states it should render
posts
↳posts/index
(invoices/index in my case). The invoices template renders however.
Handlebars:
<script type="text/x-handlebars" data-template-name="application">
<h1>Ember Committers</h1>
<nav>
{{#linkTo "index"}}Index{{/linkTo}}
{{#linkTo "about"}}About{{/linkTo}}
{{#linkTo "invoices"}}Invoices{{/linkTo}}
</nav>
{{ outlet }}
</script>
<script type="text/x-handlebars" data-template-name="invoices">
<h1>Invoices</h1>
</script>
<script type="text/x-handlebars" data-template-name="invoices/index">
<ul>
{{#each invoice in invoices }}
<li>{{#linkTo "show" invoice.id}}{{ invoice.id }}{{/linkTo }}</li>
{{/each }}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="invoices/show">
<p>Invoice - {{ name }}</p>
</script>
<script type="text/x-handlebars" data-template-name="phone">
<p>Contributor - {{ title }}</p>
</script>
<script type="text/x-handlebars" data-template-name="about">
<p>About {{ title }}</p>
</script>
<script type="text/x-handlebars" data-template-name="index">
<p>Index</p>
</script>
JavaScript:
<script type="text/javascript" defer>
var App = Ember.Application.create({
LOG_TRANSITIONS: true
});
App.ApplicationView = Ember.View.extend({
templateName: 'application'
});
App.Router.map(function () {
this.route("about");
this.resource("invoices", { path: "/invoices" }, function () {
this.resource("show", { path: "/:id" });
});
});
var invoices = [
{id: 1},
{id: 2}
];
App.AboutRoute = Ember.Route.extend({
setupController: function (controller) {
// Set the IndexController's `title`
controller.set('title', "My App");
}
});
App.InvoicesIndexController = Ember.ArrayController.extend({
invoices: invoices
});
</script>
You need to include an {{outlet}} tag in your invoices template. Since index and show are nested resources of invoices, their templates get rendered inside the outlet that you specify in the invoices template.
Take a look at the nested resources part of the Ember.js guide.

Using multiple named outlets and a wrapper view with no content in Emberjs

I'm trying to use multiple named outlets with Ember.js. Is my approach below correct?
Markup:
<script type="text/x-handlebars" data-template-name="application">
<div id="mainArea">
{{outlet main_area}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="home">
<ul id="sections">
{{outlet sections}}
</ul>
<ul id="categories">
{{outlet categories}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="sections">
{{#each section in controller}}
<li><img {{bindAttr src="section.image"}}></li>
{{/each}}
</script>
<script type="text/x-handlebars" data-template-name="categories">
{{#each category in controller}}
<img {{bindAttr src="category.image"}}>
{{/each}}
</script>​
JS Code:
Here I set the content of the various controllers to data grabbed from a server and connect outlets with their corresponding views. Since the HomeController has no content, set its content to an empty object - a hack to get the rid of this error message:
Uncaught Error: assertion failed: Cannot delegate set('categories'
) to the 'content' property of object
proxy : its 'content' is undefined.
App.Router = Ember.Router.extend({
enableLogging: false,
root: Ember.Route.extend({
index: Ember.Route.extend({
route: '/',
connectOutlets: function(router){
router.get('sectionsController').set('content',App.Section.find());
router.get('categoriesController').set('content', App.Category.find());
router.get('applicationController').connectOutlet('main_area', 'home');
router.get('homeController').connectOutlet('home', {});
router.get('homeController').connectOutlet('categories', 'categories');
router.get('homeController').connectOutlet('sections', 'sections');
}
})
})
});
​
If it's any help, I got this error because I was connecting to an Ember.ObjectController instead of Ember.Controller.