How to append Ember.View Properly - ember.js

I have recently decided to do a major upgrade with my javascript libraries and have ran into a perplexing issue with appending Ember.Views. I have been researching this issue for several hours now and have tried many things but nothing has worked.
What I want to do is quite simple: Extend Ember.View, manually create a new instance of this extended view and then append it to a div. In a much earlier version (ember.js 1.5) this was extremely straightforward. Now (ember.js 1.9) attempting the same thing results in an error.
Container was not found when looking up a views template. This is most
likely due to manually instantiating an Ember.View. See:
http://git.io/EKPpnA
Here is a very simple example that demonstrates this: http://jsfiddle.net/81dhm3ta/
html
<body>
<script data-template-name="main" type="text/x-handlebars">
Main
</script>
<div id="main" style="text-align: center;"></div>
</body>
javascript
$(document).ready(function () {
App = Ember.Application.create();
App.MainView = Ember.View.extend({
templateName: 'main',
});
App.view = App.MainView.create();
App.view.appendTo("#main");
});
Can someone show me the simplest way to do this properly?

App.view is neither a D0M element or jQuery object that you can simply append to a div. It is an Ember object of type View.
In the link given by the error, you are clearly told that you can't create views like you did in your snippet. Dynamic views must be instantiated within a parent view or directly through the container (not recommended).
Your life will be much easier if you add views within a template by just using the view helper:
<script type="text/x-handlebars" data-template-name="index">
{{view 'main'}}
</script>

Related

EmberJS: How to position the application template

I'm running into a problem. I need App.rootElement = "body", because views and components will be used all over the place. I do not want to put the entire page in a handlebars template, due to SEO and other concerns. The main application template will exist somewhere in the center of the page:
<h1>Header markup</h1>
<script type="text/x-handlebars">
<h2>Application Template</h2>
{{outlet}}
</script>
<h1>Footer markup</g1>
However, when the page is rendered, this template is appended to the end of the body, instead of staying where the template script has been placed. (see jsbin exmaple) Is there any way to tell Ember to render the application template where it is in the markup?
One hacky solution I've found is to manually move the containing element in didInsertElement, but that seems a little heavy handed and not something that would be considered a best practice. (see jsbin example)
The script tag doesn't have anything to do with placement, if you want it to live somewhere create a div tag, id it, and change the rootElement to that div tag.
<script type="text/x-handlebars">
<h2>Application Template</h2>
{{outlet}}
</script>
...
<h1>Header markup</h1>
<div id='foo'></div>
<h1>Footer markup</h1>
App.rootElement = '#foo';

EmberJS - adding some template in separated file

I'm a newbie yet on EmberJS, started to learn a week ago. Well, I have some .html file named contactsTemplate.html that is a template what I want to use. Something like this below:
<script type="text/x-handlebars" data-template-name="contacts">
<h2>My Contact List</h2>
{{#each contact in contactList}}
{{contact.name}}
{{/each}}
</script>
Great. I have a index.html file that contains an {{outlet}} expression. It means that every new content will be loaded into this space, right?
<script type="text/x-handlebars" data-template-name="application">
<h1>My Application</h1>
{{outlet}}
</script>
Ok... To manage this template named application, I've created a Controller object.
App.ApplicationController = Ember.ObjectController.extend({
...
});
Same to contacts template:
App.ContactsController = Ember.Controller.extend({
contactList: []
});
I've created two routes to manage this transition between pages:
App.Router.map(function() {
this.route("index", "/");
this.route("contacts", "/contacts");
});
My doubt is:
How can I associate this separated files to a route? I mean, when I call on browser http://mysite.com/ the index.html file should be loaded. When I call http://mysite.com/#/contacts the contactsTemplate.html should be loaded.
Sorry for the long text, and thanks for any help!
By default each declared this.route(routeName) in Router map, will have a [routeName]Controller, [routeName]Route, and expect a [routeName] template, following these conventions described in http://emberjs.com/guides/concepts/naming-conventions/.
To change from one route to other, you can use:
Inside of a controller this.transitionToRoute(routeName)
Inside of a route this.transitionTo(routeName)
Inside of a template {{#link-to "routeName" }}My route{{/link-to}}
You can find more information in the routing guide http://emberjs.com/guides/routing
I hope it helps

Use "subcontrollers" in EmberJS

i'm having some trouble designing an EmberJS layout. I have a view divided in two parts :
a content library on the left
a playlist editor on the right
Currently, those two elements share the same controller.
I can't figure how to use two different controllers for those two sides to be able to re-use the content library in other views or even having a view with two playlist editors.
My root view looks like this so far :
<script type="text/x-handlebars" data-template-name="playlists">
<div id="library">{{template library}}</div>
<div id="playlistEditor">{{template playlisteditor}}</div>
</script>
I saw docs about the {{control}} helper, but it is unstable and i'm not sure this is what i'm looking for.
Thanks !
Okay, i found the answer, i had to use the {{render}} helper, like that :
<script type="text/x-handlebars" data-template-name="playlists">
<div id="library">{{render "library" library}}</div>
<div id="playlistEditor">{{render "playlisteditor" playlist}}</div>
</script>
Then, in my route :
App.PlaylistsRoute = Ember.Route.extend({
setupController: function(controller) {
controller.set('playlist', playlist);
controller.set('library', library);
}
});
Then, this EmberJS will automatically wire the App.PlaylisteditorController, the App.LibraryController and the views playlisteditor and library. Awesome.

Updating partial style content

I would like to do the following handlebar script:
The color:{{object.labelColor}} seems not working (Cf. other post).
One solution seems to bind the complete style attribute on the "javascript side" but I would like to avoid managing the "fixed" part of the style (text-align:left) on that side.
Is there a solution to make something similar to my sample code (dynamic part on the js side,fixed part on the html view) ?
<div class="label" style="color:{{object.labelColor}};text-align:left">{{object.name}}</div>
You could use 'classNameBindings', and define a set of css rules to the corresponding classes.
Js
Ember.View.create({
classNameBindings: ['isUrgent'] // array of class names
isUrgent: true //conditional to set class name
});
css
.is-urgent{
background-color: #356aa0;
}
Resource
http://emberjs.com/api/classes/Ember.ContainerView.html#property_classNameBindings
If you have to use styles instead of classes, and want to change only a portion of the style strings at the time, one alternative would be using $.css, applying the style changes you want. For example:
<script type="text/x-handlebars">
<h1>App</h1>
{{view App.SomeView}}
</script>
<script type="text/x-handlebars" data-template-name="some-view">
<div style="color:#00F;text-align:left">
Some View<br />
<button {{action changeColor on="click"}}>Change Color</button>
</div>
</script>
<script type="text/javascript">
App = Em.Application.create();
App.SomeView = Em.View.extend({
templateName: 'some-view',
changeColor: function(e) {
console.log('changing color');
this.$('div').css('color', '#F00');
}
});
</script>
In the script above I'm using jQuery's css function to change the color attribute whatever elements my selector returns from within SomeView instance (in this case as I only have one div, I'm using the element as a selector). There are other (and likely better) ways to do this, but I hope this helps.
The problem with this solution as it is, is that you can't keep the state of the style attribute as it's not bound to any property, that's why I think binding classes would be better in the long run.

Can't get value from a view's controller within a containerview in Ember

Hello Ember jedi masters,
I'm learning Ember's framework and get some confuses while using it with handlebars helpers.
Firstly I created some view templates in my js and html and used a containerView to group those templates.
But I'm having a trouble that I can't display the value I described in my controllers of those template views.
My HTML part is like this:
<script type="text/x-handlebars" data-template-name="main">
<p>this is main template</p>
{{outlet nav}}
</script>
<script type="text/x-handlebars" data-template-name="nav">
</script>
<script type="text/x-handlebars" data-template-name="child">
<p>this is the child in nav, value is {{value}}</p>
</script>
Here's my sample code on jsfiddle (including the JS part):
http://jsfiddle.net/9K7D4/
my question is:
while the child view is rendered from container view, I couldn't get the value which is defined in my child view's controller. I must missed something in the document.. just couldn't figure it out..
Thanks for helping me!
In your example, though the child controller instantiated during application initialization, it is not connected as the controller of the child view (I think there something missing in the framework).
Anyway, if you want to refer it in the child view, you have to lookup through the router with valueBinding: 'App.router.cController.content.value'. Note I'm using lowercase, as conventionnally, ember will create an instance of XxxController as xxxController.
Then in the template, as you want to use a property from the view itself, you must use the view keyword in order to do it.
see http://jsfiddle.net/9K7D4/14/