EmberJS: How to position the application template - ember.js

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';

Related

ember.js render partial on any template

I need to pick up an ember.js project to finish a few things. Unfortunately I don't have time to learn the whole framework and features but I was wondering how I create a partial.
I read the documentation below but don't really understand what goes where. I presume the second block of text goes in the .hbs template but where do I put the top block so that the second block can be rendered on any .hbs template?
<script type="text/x-handlebars" data-template-name='_author'>
Written by {{author.firstName}} {{author.lastName}}
</script>
<script type="text/x-handlebars" data-template-name='post'>
<h1>{{title}}</h1>
<div>{{body}}</div>
{{partial "author"}}
</script>
I worked it out, I didn't add the partial to:
EmberHandlebarsLoader.loadTemplates([])

How to append Ember.View Properly

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>

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/

Getting the content rendered inside a #each ember template helper, without the #each content binding

/START description of why
I'm doing a 'load more' type of interaction: user gets at bottom of a page, I load more content.
As I'm using a plugin that formats content in a 'pinterest-style' (masonry), I need to take the output of a rest call, formatted using an ember view, and i'm doing something like:
<div id="list">
</div>
<div id="hidden" style="display:none">
{{#each item in App.itemsController}}
test {{item.id}}
<br />
{{/each}}
</div>
What I want to do is, load the content in the hidden div, and then pass its HTML generated content to the plugin to process in my formatted list view.
If I just copy the #hidden content, the Ember scripts get in, and on subsequent 'load more', content is inserted in the #list, in addition of going in the #hidden div.
That's because I copied the entire handlebars.
So I get rid of the container tag, the one I supposed was wrapping the controller content binding, but even when stripping it from the content I pass to #list, the #list still auto-updates when a 'load more' is called.
I know that's a dirty hackish thing, but in order to improve performance in the client I must take a similar route.
/END description of why
//ACTUAL QUESTION ;)
Given this background, the question is, stripping the container metamorph script tags (like the ones here below), and just take the content inside them, shouldn't get rid of the auto-updating content functionality?
<script id="metamorph-X-start" type="text/x-placeholder"></script>
//ALL THE CONTENT
<script id="metamorph-X-end" type="text/x-placeholder"></script>
Inside those, I just have the actual content generated, like:
<script id="metamorph-9-start" type="text/x-placeholder"></script>
test <script id="metamorph-59-start" type="text/x-placeholder"></script>2873<script id="metamorph-59-end" type="text/x-placeholder"></script>
<br>
<script id="metamorph-9-end" type="text/x-placeholder"></script>
<script id="metamorph-10-start" type="text/x-placeholder"></script>
test <script id="metamorph-60-start" type="text/x-placeholder"></script>2872<script id="metamorph-60-end" type="text/x-placeholder"></script>
<br>
<script id="metamorph-10-end" type="text/x-placeholder"></script>
The alternative is programmatically render the template inside a variable and process that, which is surely a better way of doing this, but I just wonder how the #each binding works internally as I thought the metamorph was doing that.
Have you looked into using a CollectionView and calling the plugin through the didInsertElement callback?
e.g.
MyList = Ember.CollectionView.extend({
itemViewClass: 'App.ListItem',
didInsertElement: function(){
view.$().jqueryPlugin({ ... })
}
})