Rendering views in Ember globally - javascript

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

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>
...

Ember replacing html content

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

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

AngularJS dynamically set param of ngInclude based on route

I'm trying to dynamically include a template into my index.html. The general structure of index.html is:
<body>
<header ng-controller="Main">
<section>
<!-- global stuff -->
</section>
<section ng-include="moduleName + '/views/menubar.html'">
<!-- module-based stuff -->
</section>
</header>
<div id="view" ng-view></div>
</body>
Sample URL
example.com/<app_name>/index.html#/<module_name>[/method_name]
I can't figure out how to update $scope.moduleName when the route changes. My trouble is two-fold:
The header's controller is Main, not the controller associated with the view, so I can't? update $scope.moduleName from the view's controller (because Main and the view's controller are siblings).
In Main, I tried setting a $scope.$on('$routeChangeSuccess',…), but apparently it is not notified of route changes.
I've thought of setting up a $rootScope.$on listener (as described in SO#15355346) for the route change and broadcasting down to children, who then emit back up their route, which is broadcasted back down so it is available to Main. But that seems heinous.
And I would really prefer to keep the header outside of ng-view.
EDIT I noticed that $route.current.scope has an object named with module_name (possibly because the name of the controller associated with the route's module_name is the same). I'm wondering if I might be able to somehow use the name of that object…
It's hard to say what's wrong in your code without the full picture. Things you show look fine to me.
Please see this plunk I've created to display the ability to do it. Take note that you also can extend route objects with custom properties, like moduleName here:
$routeProvider.when('/page1', {
template: 'one',
controller: 'one',
moduleName: 'firstModule'
});

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);
}
});

Categories

Resources