Ember replacing html content - javascript

I've just started learning ember am trying to make a link that replaces other html, currently I have written this:
<script type="text/x-handlebars" id="about">
{{#each}}
<h2>{{#link-to 'quarter' this}}{{title}}{{/link-to}}</h2>
{{/each}}
</script>
Now I want to make the quarter content load in the same about template replacing that each loop, how should I go about it?
Again, I'm totally new to ember and it's own guides section is a bit too convoluted for me to find the answer.

Since About is not a resource route, you have to use custom outlet in your about template:
<div class="quarter">{{outlet quarter}}</div>
Then in your QuarterRoute:
App.QuarterRoute = Ember.Route.extend({
renderTemplate: function() {
this.render({ outlet: 'quarter' });
}
});
If you have a Quarters resource routes, you could just nest your routes and just a have simple outlet in your quarters template.
App.Router.map(function() {
this.resource('quarters', function() {
this.resource('quarter');
});
});

Related

Ember.js Render multiple views inside static HTML

I'm new to Ember and I'm stuck trying to render views.
The application in context is not a single page application but so far Ember has been playing nice until I started dealing with views.
I'm trying to render more than one view on a single page (which is like a dashboard and has tons of static HTML and a few containers, one for each view).
Sample HTML:
Let's say I would like to render two lists, one inside the "left-container" div and the other inside the right container.
<div class="static-header></div>
<!-- more static content goes here -->
<div id="left-container"></div>
<!-- more static content goes here -->
<div id="right-container"></div>
...
I've tried creating different views and inserting them using the appendTo method (which is described in the Defining a View section of Ember guides) but it throws the 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
and I couldn't find my way using the link that it points to.
Ember code:
var App = Ember.Application.create({});
App.HomeViewLeft = Ember.View.extend({
templateName: 'home-left',
});
var view = App.HomeViewLeft.create();
view.appendTo('#left-container');
I have also tried using a ContainerView as described in Ember api docs:
App.HomeViewLeft = Ember.View.extend({
templateName: 'home-left',
});
var containerView = Ember.ContainerView.create({
classNames: ['container-view'],
});
containerView.pushObject(App.HomeViewLeft.create());
containerView.appendTo('left-container');
But I get the same error.
How should I render each view inside the #left-container and #right-container respectively?
Thanks in advance.
Template:
<div id="here"></div>
<script type="text/x-handlebars" data-template-name="components/my-foo">
{{text}}
</script>
JS:
App = Ember.Application.create({});
Ember.Application.initializer({
name: 'stand-alone-components',
initialize: function(container, application) {
App.MyFooComponent.create({text: 'Hello World', container: container}).appendTo('#here');
}
});
App.MyFooComponent = Ember.Component.extend({
init: function() {
this._super();
this.set('layout', Ember.TEMPLATES['components/my-foo']);
}
});
http://emberjs.jsbin.com/nekowidera/1/edit?html,js,output
It looks like you are trying to make views behave like partials
Move anything static into a partial and include it in your main template like so:
{{partial "header"}}
The lists you want to render can be turned into a component (if the only thing that changes in them is the data).
So you end up with a single view that contains partials and components:
<div class="static-header>{{partial "header"}}</div>
{{partial "static-content"}}
<div id="left-container">{{list-component data=firstList}}</div>
{{partial "static-content"}}
<div id="right-container">{{list-component data=secondList}}</div>
...

Rendering views in Ember globally

I’m quite new in Ember world (came from Backbone/Marionette powered apps), and some things are quite unclear for me.
I’d like to render 3 views in my application: Sidebar, Navigation, and view with actual content (based on my path).
In order to do that, I added to my application tempalate 3 outlets:
<nav id="main_navigation">{{outlet navigation}}</nav>
<!-- some html goes here... -->
<nav id="sidebar_navigation">{{outlet sidebar}}</nav>
<section id="content">{{outlet}}</nav>
Because I want to display them on every page, I created ApplicationRoute with following code:
App.ApplicationRoute = Ember.Route.extend
activate: ->
#render "sidebar",
outlet: "sidebar"
# into "application"
Of course I’ve got sidebar template, but I don’t think its code is relevant here (I can attach it if it’ll be relevant). Unfortunately, this leads to following error:
Error while loading route: Error: Assertion Failed: An outlet (sidebar) was specified but was not found.
If I try to comment out into "application", then I get this: Error while loading route: TypeError: Cannot read property 'connectOutlet' of undefined
I’d be really greatful, if someone tell me how to render this templates globally (on all pages).
The activate hook is executed when the router enters the route. The template must already be in scope in order to render an item into it. That being said, you can just render the application template first, then render the navbar/sidebar using the renderTemplate hook.
App.ApplicationRoute = Ember.Route.extend({
renderTemplate: function(){
this.render(); // render the application template
this.render('nav',{
into: 'application',
outlet: 'navigation'});
this.render('side',{
into: 'application',
outlet: 'sidebar'});
}
});
http://emberjs.jsbin.com/lemutisa/1/edit
Additionally you could do this all even easier using render in the template
<script type="text/x-handlebars">
Appplication
{{render 'nav'}}
{{render 'side'}}
<section id="content">{{outlet}}</nav>
</script>
http://emberjs.jsbin.com/lemutisa/2/edit

How to make something happen after a template has rendered in emberjs

So the concept is simple: You come to the app, you have a default template, with a default navigation element. You click a link in that navigation element it renders a new template: #/rails.
From here the default navigation needs to be hidden, and your new nav needs to be rendered.
The way i attempted to approach this, seems a bit silly: what I did was,
SG.Router.map(function(){
this.resource('rails');
});
$(document).ready(function() {
if($('#rails-nav').length !== 0){
$('#main-nav').hide();
}
});
Now the issue with this is that if you go from the default application template, to the rails template via the link - you get two navs unless you refresh that page. My friend stated that I should use something like:
{{outlet nav}} and then render a navigation based on template. The issue is I don't know how to set this up and I have been looking all over the ember site.
Could some one help me out?
If i understood correctly, when you say default template you mean the application template, where all other templates are rendered within its {{outlet}} helper.
There are several approaches to achieve what you want, but a simple one i think would be to use the index template as your default template. In this case evertyhting will be much simpler and work as you require, since you can specify whether the navigation element is shown by placing it inside a template or not.
http://emberjs.jsbin.com/sume/1/edit
hbs
<script type="text/x-handlebars">
<h2> Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
This is the default template using <i>index</i>
<br/>
<br/>
<span style="background-color:grey">this is the nav part {{#link-to 'rails'}}go to rails{{/link-to}}</span>
</script>
<script type="text/x-handlebars" data-template-name="rails">
this is the rails app
</script>
js
App = Ember.Application.create();
App.Router.map(function() {
this.resource("rails");
});
Also to make this answer a bit more relevant to the title of the question, in order to do something when a template has rendered one way would be to use the didInsertElement callback of the View class.
App.RailsView = Ember.View.extend({
didInsertElement:function(){
if($('#rails-nav').length !== 0){
$('#main-nav').hide();
}
}
});
http://emberjs.jsbin.com/dido/1/edit

From Rails & Backbone to ember

I'm trying out ember js on a personal project. I'm struggling with understanding what part plays the different components of Ember.
I'm quite familiar with Rails, and I've used backbone to some extent (never used everything related to routing), and get how the two of them work, and what kind of objects plays which part of MVC.
With Ember, things are not that clear and seems a bit less easy. I've read the guides and a few posts, but I'm still struggling to get going. I get the model part, which is fairly similar to its rails and backbone counterpart. I get templates, handlebars, that stuff too. The router is similar to rails router.
Then there is Controllers, Routes, and Views. From what I understood, Views represent a portion of the ui, and handles user interaction. It's the controller/routes roles that I don't get very much.
To be more concrete: I want my app to have a nav bar (with links to page sections), and a "user connexion widget", displaying user data if he's connected, allow him to do so if not, log in via facebook etc.
The navbar seems appropriate for a View, however I need to keep the state somewhere (to highlight the current page), which seems to be the controller role. And the user widget seems appropriate for a controller, but there's only one controller per route, so how to do this ?
Thanks a lot for your time, I hope I was clear enough!
:)
Controller stores the state of your application. Router manages different states of your application. You're correct, there's only one controller per route, but you can access other controllers as well.
Assuming this your html:
<script type="text/x-handlebars" data-template-name="application">
<div class="main-content">
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="index">
<div class="nav-bar">
<div class="user">
{{#if isLoggedIn}}
<div class="user-name">{{userName}}</div>
{{else}}
<button {{action "login" target="App.UserController"}}>
Login
</button>
{{/if}}
</div>
</div>
<div class="content">some other amazing content here</div>
</script>
and JS:
var App = Ember.Application.create({
LOG_TRANSITIONS: true,
rootElement: '#ember-app'
});
App.Router.map(function () {
this.route('user');
});
App.IndexRoute = Ember.Route.extend({
setupController: function(controller, model) {
this.controller.set('isLoggedIn', this.controllerFor('user').get('isLoggedIn'));
}
});
App.UserController = Ember.ObjectController.extend({
isLoggedIn: false,
userName: 'emberjs',
login: function () {
this.set('isLoggedIn', true);
}
});
App.NavbarView = Ember.View.create({
loggedInBinding: Ember.Binding.oneWay('App.UserController.isLoggedIn')
});
If you need to access another controller from your route, you can do this:
App.IndexRoute = Ember.Route.extend(function () {
setupController: function () {
var userController = this.controllerFor('user');
console.log('this is a user controller instance', userController);
}
});

Ember.js handlebars if, else statement

I'm hoping someone can explain what I'm doing wrong here. I'm using Ember.js with handlebars templates, I've tried a number of ways to get handlebars #if else working for me but it always returns both the contents of if and else.. Here's the code I'm currently using.
App.js:
App = Ember.Application.create({
selectedView: "Home",
IsHome: function() {
this.get('selectedView') === 'Home'
}.property('selectedView')
});
index.html head contains:
<script type="text/x-handlebars" data-template-name="home-view">
Hello, This is the home view.
</script>
<script type="text/x-handlebars" data-template-name="edit-account">
Hello, This is the account edit view.
</script>
and in the body:
<script type="text/x-handlebars">
{{#if App.IsHome}}
{{view HomeView}}
{{else}}
{{view editAccountView}}
{{/if}}
</script>
This ends up showing both views in the body of the page. Any advice is appreciated,
thanks
Steve
The fundamental reason for your problem is the Handlebars view helper ( {{view MyView}} ) expects a path parameter to an Ember “class”, not an instance of a class. To create a view class use the extend method of Ember.View. The Handlebars view helper will instantiate your view class and append it to the document for you.
See this post for more information on the Ember object model and the differences between Ember’s extend and create methods: http://ember-object-model.notlong.com.
Here is your example with a few changes made to correct the points I made above. http://jsfiddle.net/ethan_selzer/kcjzw/217/
Regards,
Ethan
That's because you are appending both views (homeView and editAccountView) manually with appendTo.
Also, avoid defining views within the App create() function. Therefore, create your App:
App = Ember.Application.create({
ready: function() {
App.MainView.create().append();
}
});
where App.MainView is your top-level view defined by:
App.MainView = Ember.View.extend({
templateName: 'main-view',
selectedView: "Home",
isHome: function() {
this.get('selectedView') === 'Home'
},
homeView: Ember.View.extend({
templateName: 'home-view'
}),
editAccountView: Ember.View.extend({
templateName: 'edit-account'
})
});
with the handlebars template:
<script type="text/x-handlebars" data-template-name="main-view">
{{#if view.isHome}}
{{view view.homeView}}
{{else}}
{{view view.editAccountView}}
{{/if}}
</script>

Categories

Resources