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")
});
Related
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#/
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.
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.
I think this should be a really easy fix, i just cant figure it out.
I have this model in my ApplicationRoute:
App.ApplicationRoute = Ember.Route.extend({
model: function() {
return {
sideNav: data.side,
breadcrumbs: Util.breadcrumbs()
}
}
});
application template:
<script type="text/x-handlebars" data-template-name="application">
{{outlet}}
</script>
overview template:
<script type="text/x-handlebars" data-template-name="overview">
{{partial side}}
</script>
_side partial:
<script type="text/x-handlebars" id="_side">
{{#each model.side}}
<i {{bindAttr class="iconClass"}}></i><p>{{label}}</p>
{{/each}}
</script>
When I load my overview route, the stuff in there loads, but the application model is not applied to the side partial like I would like it to be... there may be a better way to do this. Thanks!
It looks like you have two problems:
You are binding to side instead of sideNav inside your partial.
You're trying to access the model of ApplicationRoute inside of the overview template (which presumably has its own route and controller)
Partials don't change context, so they don't add any complexity on their own. For instance, if we restrict ourselves to the application template, the following will work:
App.ApplicationRoute = Ember.Route.extend({
model: function() {
return {
foo: 'bar'
};
}
});
<script type="text/x-handlebars" data-template-name="application">
{{partial partial}}
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="_partial">
{{foo}}
</script>
However, if you want to get at the application model inside of a nested route, you'll need to ask for it. For example, inside of the (default) index route, you could add the following:
App.IndexRoute = Ember.Route.extend({
model: function() {
return this.modelFor('application');
}
});
<script type="text/x-handlebars" data-template-name="index">
{{partial partial}}
</script>
You can see both examples in this jsfiddle.
I'm new to Ember.js.
I want to focus on TextField(in sample, id="text") after initialization,
but in ready function, doesn't work focus method...
<body>
<!-- library load -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script>!window.jQuery && document.write(unescape('%3Cscript src="js/libs/jquery-1.6.1.min.js"%3E%3C/script%3E'))</script>
<script src="http://cloud.github.com/downloads/emberjs/ember.js/ember-0.9.5.min.js"></script>
<script type="text/x-handlebars">
{{view Em.TextField id="text"}} // want to focus it.
</script>
<script type="text/javascript">
var App = Em.Application.create();
App.ready = function() {
$('#text').focus(); // does'nt work.
}
</script>
</body>
The following code does work:
<script type="text/x-handlebars">
{{view App.TextField id="text"}} // want to focus it.
</script>
<script type="text/javascript">
var App = Em.Application.create();
App.TextField = Em.TextField.extend({
didInsertElement: function() {
this.$().focus();
}
});
</script>
Subclassing TextField and then spreading a custom View around your templates seemed a bit messy to me, so I wrote this little 1kb package that lets you do this more elegantly, directly in the template, without any further coding:
<body>
<!-- all the libraries -->
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.3.0/handlebars.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/ember.js/1.2.0/ember.min.js"></script>
<script src="http://rawgithub.com/AndreasPizsa/ember-autofocus/master/dist/ember-autofocus.min.js"></script>
<!-- your template -->
<script type="text/x-handlebars">
Hello, world! {{ input }}
:
: more elements here
:
{{ autofocus }} {# <<<<-- Magic happens here #}
</script>
<!-- your app -->
<script>
Ember.Application.create();
</script>
</body>
You can get it from https://github.com/AndreasPizsa/ember-autofocus
or with bower install ember-autofocus. I appreciate feedback!