Understanding Ember Routes and Models - ember.js

I try to understand how Ember works and I have an issue I can't understand. I am following a tutorial (guides.emberjs.com/v1.10.0/) and I don't understand why I only see an element when I go on a page when I click (and doesn't work with a direct link).
I think some screenshots will be helpful to understand my issue.
This is what I have when I visit "index.html#/posts/1". No article is displayed.
http://i.stack.imgur.com/qzwlq.png
This is what I have when I visit "index.html#/posts" and then click on Rails is Omakase on the left. An article is displayed whereas the link is on my browser is "index.html#/posts/1" (and when I refresh nothing is displayed).
http://i.stack.imgur.com/YpmzX.png
This is my index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Blog tuto</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/2.3.2/css/bootstrap-combined.no-icons.min.css">
</head>
<body>
<script type="text/x-handlebars">
<div class="navbar">
<div class="navbar-inner">
<a class="brand" href="#">Bloggr</a>
<ul class="nav">
<li>{{#link-to "posts.index"}}Posts{{/link-to}}</li>
<li>{{#link-to "about"}}About{{/link-to}}</li>
</ul>
</div>
</div>
{{outlet}}
</script>
<script type="text/x-handlebars" id="about">
<p>
Lorem ipsum about
</p>
</script>
<script type="text/x-handlebars" id="posts">
<div class="container-fluid">
<div class="row-fluid">
<div class="span4">
<table class="table">
<thead>
<tr><th>Recent Posts</th></tr>
</thead>
{{#each post in model}}
<tr>
{{#link-to "posts.post" post}}
<td>{{post.title}} <small class="muted">by {{post.author}}</small></td>
{{/link-to}}
</tr>
{{/each}}
</table>
</div>
<div class="span8">
{{outlet}}
</div>
</div>
</div>
</script>
<script type="text/x-handlebars" id="posts/post">
{{#if isEditing}}
{{partial "post/edit"}}
<button {{action "doneEditing"}}>Done</button>
{{else}}
<button {{action "edit"}}>Edit</button>
{{/if}}
<h1>{{title}}</h1>
<h2><small class="muted">by {{author}}</small></h2>
<hr>
<div class="intro">
{{exerpt}}
</div>
<div class="below-the-fold">
{{body}}
</div>
</script>
<script type="text/x-handlebars" id="post/edit">
<p>{{input type="text" value=title}}</p>
<p>{{input type="text" value=exerpt}}</p>
<p>{{textarea value=body}}</p>
</script>
<script src="../js/libs/jquery.min.js"></script>
<script src="../js/libs/handlebars.js"></script>
<script src="../js/libs/ember.js"></script>
<script src="../js/libs/ember-data.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/showdown/0.3.1/showdown.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.1.0/moment.min.js"></script>
<script src="app.js"></script>
</body>
</html>
And app.js
App = Ember.Application.create();
App.Router.map(function() {
this.route('about');
this.resource('posts', function () {
this.route('post', {path: ':post_id'});
});
});
App.PostsRoute = Ember.Route.extend({
model: function () {
return posts;
}
});
App.PostsPostRoute = Ember.Route.extend({
model: function (params) {
return posts.findBy('id', params.post_id);
}
});
App.PostsPostController = Ember.ObjectController.extend({
isEditing: false,
actions: {
edit: function () {
this.set('isEditing', true);
},
doneEditing: function () {
this.set('isEditing', false);
}
}
});
var posts = [{
id: 1,
title: "Rails is Omakase",
author: "mc100s",
date: new Date('08-06-2015'),
exerpt: "Lorem ipsum dolor sit amet",
body: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}, {
id: 2,
title: "The Parley Letter",
author: "mc100s",
date: new Date('08-06-2015'),
exerpt: "Duis aute irure dolor in reprehenderit",
body: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}];
Thank you for your help

When you click link, model is passed directly to the route and route's model hook is not fired, so you see article. When you reload route model hook is fired and something goes wrong.
Make string id, because params.post_id is String.
findBy is Ember.Array method. http://emberjs.com/api/classes/Ember.Array.html#method_findBy
I would try:
var posts = Ember.A([{
// as is
}]);
Next change ObjectController to Controller (ObjectController is deprecated) and use {{model.title}} instead of {{title}} in template:
<script type="text/x-handlebars" id="posts/post">
{{#if isEditing}}
{{partial "post/edit"}}
<button {{action "doneEditing"}}>Done</button>
{{else}}
<button {{action "edit"}}>Edit</button>
{{/if}}
<h1>{{model.title}}</h1>
<h2><small class="muted">by {{model.author}}</small></h2>
<hr>
<div class="intro">
{{model.exerpt}}
</div>
<div class="below-the-fold">
{{model.body}}
</div>
working jsbin here: http://jsbin.com/pozabixeka/edit?html,js,output

Related

How to render Django TextField within VueJs Template

I am writing my backend using DRF and using VueJS frontend templates. In the admin panel I use Ckeditor to edit textfield.
class ArticleModelForm(forms.ModelForm):
content = forms.CharField(widget=CKEditorUploadingWidget)
class Meta:
model=Article
fields = [ "title", "slug" "published_at"]
While rendering a post TextField I can not use template filters to render correctly, so text seems ruined. I have tried lots of things but no success yet.
<template>
<div>
<div class="container negative-margin-top150">
<div class="col col-xl-8 m-auto col-lg-12 col-md-12 col-sm-12 col-12">
<div class="ui-block">
<!-- Single Post -->
<article class="hentry blog-post single-post single-post-v1">
<div class="post-content-wrap">
<div class="post-content" >
<p class="post-paragraph">
{{article.content}}
</p>
<p>{{content}}</p>
</div>
</div>
</article>
<!-- ... end Single Post -->
</div>
</div>
</div>
</div>
</template>
and my script is below
<script>
import axios from 'axios';
export default {
name: "Article",
props: {
slug: {
type: String,
required: true
}
},
data() {
return {
article: {},
content: `${content}`,
}
},
methods: {
setPageTitle(title) {
document.title = title;
},
setRequestUser() {
this.requestUser = window.localStorage.getItem("username");
},
getArticle(slug) {
axios.get(`http://localhost:8000/api/articles/${this.slug}`)
.then(response => {
this.article = response.data;
this.setPageTitle(response.data.title);
this.content = window.content;
});
}
},
created() {
this.getArticle();
this.setRequestUser();
},
};
</script>
Now in the browser my text is rendered with template tags
<h3>The standard Lorem Ipsum passage, used since the 1500s</h3>
<p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
Anybody here who can point me in the right direction?
You need to use v-html attribute to render raw conent.
https://v2.vuejs.org/v2/guide/syntax.html

Apply Equalizer on Orbit slider in Foundation 6

I am trying to get all of the slides in my orbit slider to be the height of the largest slide.
Here is my markup:
$(document).ready(function(){
$('.orbit-container').equalize('outerHeight');
});
<div class="orbit" data-orbit="" role="region" data-auto-play="false" data-resize="7sdsk0-orbit" id="7sdsk0-orbit" data-t="3k1v70-t"><button class="orbit-previous" tabindex="0"><span class="show-for-sr">Previous Slide</span>◀︎</button><button class="orbit-next" tabindex="0"><span class="show-for-sr">Next Slide</span>▶︎</button><div class="orbit-wrapper">
<ul class="orbit-container" data-options="bullets: true; autoPlay:false;" data-auto-play="false" data-equalizer="" data-equalize-on-stack="true" data-equalize-by-row="true" data-resize="lo2q16-eq" data-mutate="k2tsn5-eq" data-t="fgxh6n-t" tabindex="0" style="height: 0px;" data-events="mutate">
<li data-equalizer-watch class="orbit-slide" data-slide="0">
<div>
<div class="text-container">
<h1>Arthritis. Give Before it takes.</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisi elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, nostrud</p>
Learn More
</div>
<div class="inner-overlay"> </div>
<img alt="" class="orbit-image desktop" src="/AS/media/AS/Homepage%20Billboards/billboard-tweaked.jpg?ext=.jpg">
<img alt="" class="orbit-image mobile" src="/AS/media/AS/Homepage%20Billboards/mobile-cropped.jpg?ext=.jpg">
</div>
</li>
<li data-equalizer-watch class="orbit-slide is-active" data-slide="1" aria-live="polite">
<div>
<div class="text-container">
<h1>Lorem ipsum dolor sit amet</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisi elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, nostrud</p>
Learn More
</div>
<div class="inner-overlay"> </div>
<img alt="" class="orbit-image desktop" src="/AS/media/AS/Homepage%20Billboards/billboard-tweaked.jpg?ext=.jpg">
<img alt="" class="orbit-image mobile" src="/AS/media/AS/Test%20Images/rough-mobile.jpg?ext=.jpg">
</div>
</li>
</ul>
</div>
On each li, an inline style is being applied of height="auto", so the slides are different heights. Even if I call that function after the window has loaded, it has the same effect.
Am I missing something?

How to reverse a model's output in ember?

I'm trying to reverse a model's output in ember. It was suggested (via IRC channel) that I use a computed property, but I am having a tough time figuring out how to do this.
I'm trying to do this in the controller. Any help would be appreciated, as I am pretty new to ember.
controllers/comments.js
export default Ember.Controller.extend({
model: 'comment',
reverse: function(){
return this.get('model').toArray().reverse();
}.property('model.#each')
});
comments.hbs
{{#each model as |item|}}
<div class="each__comment">
<div class="comment__image">
<img src="{{ item.img_src }}">
</div>
<div class="comment__text">
<h2 class="comment__author">{{item.full_name}}</h2>
<h3 class="comment__title">{{item.title}}</h3>
<p class="comment__description">{{item.description}} </p>
<p class="comment__date">{{ item.date_posted }}</p>
</div>
</div>
{{/each}}
routes/comments.js
export default Ember.Route.extend({
model: function() {
return this.store.find('comment');
},
actions: {
createComment: function() {
var title = this.controller.get('newComment');
if (title && !title.trim()) {
this.set('newComment', '');
return;
}
var comment = this.store.createRecord('comment', {
description: title
});
this.controller.set('newComment', '');
// Save the new model
comment.save();
}
}
});
models/comment.js
var Comment = DS.Model.extend({
img_src: DS.attr('string', {
defaultValue: '/assets/images/user-img-4.png'
}),
full_name: DS.attr('string', {
defaultValue: 'Nick Beattie'
}),
title: DS.attr('string', {
defaultValue: 'Developer'
}),
description: DS.attr('string', {
defaultValue: 'description duh'
}),
date_posted: DS.attr('string', {
defaultValue: 'Tues Nov 17th'
})
});
Comment.reopenClass({
FIXTURES: [
{
"id": "1",
"img_src": "/assets/images/user-img-1.png",
"full_name": "Tony Jackson",
"title": "Product Designer",
"description": "Morbi at augue eu felis cursus feugiat. Pellentesque a dui ut magna tristique imperdiet. Donec nec rutrum purus. Quisque id nibh metus. Proin condimentum non ipsum at sagittis. Suspendisse potenti.",
"date_posted": "Tues Apr 10th"
},
{
"id": "2",
"img_src": "/assets/images/user-img-2.png",
"full_name": "Laura Malroy",
"title": "Strategist",
"description": "Proin egestas turpis nec orci vulputate accumsan. Nullam gravida ultricies feugiat. Praesent molestie pulvinar egestas.",
"date_posted": "Sat May 14th"
},
{
"id": "3",
"img_src": "/assets/images/user-img-3.png",
"full_name": "Nicole Emsley",
"title": "Illustrator",
"description": "Etiam sed cursus mi. Morbi neque elit, ullamcorper et justo ut, pharetra egestas metus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Morbi magna dolor, pretium eget convallis ac, faucibus quis elit. Pellentesque vehicula vestibulum ante in bibendum. Nam tristique nec mi sit amet semper.",
"date_posted": "Mon Jun 9th"
}
]
});
export default Comment;
You are practically there, just switch to using the computed property in the template instead of the model property.
{{#each reverse as |item|}}
<div class="each__comment">
<div class="comment__image">
<img src="{{ item.img_src }}">
</div>
<div class="comment__text">
<h2 class="comment__author">{{item.full_name}}</h2>
<h3 class="comment__title">{{item.title}}</h3>
<p class="comment__description">{{item.description}} </p>
<p class="comment__date">{{ item.date_posted }}</p>
</div>
</div>
{{/each}}
Also you don't need to define the model property in your controller, it's just going to get overwritten by the route. Additionally, the #each notation is generally used for watching a particular property on each item, if you just want to see if the collection grows or shrinks you can watch length or [].
export default Ember.Controller.extend({
reverse: function(){
return this.get('model').toArray().reverse();
}.property('model.[]')
});
Example: http://emberjs.jsbin.com/rucojiyemu/1/edit?html,js,output

Backbone Underscore error on template render: Uncaught TypeError: Object #<Object> has no method 'get'

At the console.log line in the render method below, it shows that this.member instance is exactly what it should be. So member object is good. I've spit out the string in tpl and it's what it should be. So what's causing the error in topic title?
Additional info: This view is a subview rendered by parent. I'm using Backbone.Subviews.
Thanks a lot for your help. I'm spinning my wheels :-/
Here is my code...
EDIT: Changed member object attrib references and now it works...
Template...
<div class="wrap-profile container">
<div class="profile-pic">
<div class="pic">
<img src="<%= pathUploads %><%= member.photo_profile %>" width="400" height="600" id="<%= member.id %>" class="photo-img">
</div>
</div>
<div class="profile-info">
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent consectetur urna nec erat pretium tempus.
</div>
<div>
Morbi nec arcu at leo lobortis egestas. Phasellus sagittis neque dolor, ut congue lorem egestas id.m laoreet, vitae tristique lorem sollicitudin.
</div>
<div>
In vel libero eget enim rhoncus suscipit. Nunc tristique in nisi eget bibendum. Mauris et pulvinar orci.
</div>
<div>
Quisque eget sem id dolor tempus dictum. Pellentesque luctus scelerisque lacinia.
</div>
<div>
Sed gravida rutrum bibendum. Aenean condimentum eu dui nec adipiscing. Duis sagittis pharetra enim.
</div>
</div>
</div>
The view js...
// ProfileView.js
define( function(require) {
"use strict";
var $ = require('jquery'),
_ = require('underscore'),
Backbone = require('backbone'),
Helper = require('helper'),
tpl = require('text!templates/profilePicTemplate.html'),
template = _.template(tpl);
return Backbone.View.extend({
el: $("#profile"),
initialize: function(member) {
var self = this;
this.member = member;
},
render: function() {
var data = {
pathUploads: Helper.global.pathUploads,
member: this.member
};
console.log(this.member);
this.$el.html(template(data));
return this;
},
destroy: function() {
template = null
this.member = null;
}
});
});
The evidence points quite directly at this.member being a plain old javascript object instead of an instance of a Backbone.Model subclass. You seem to be aware of this, so I think it's a case of "no really, hear us now and believe us later". To test this theory, swap in this snippet.
var data = {
pathUploads: Helper.global.pathUploads,
member: new Backbone.Model(this.member)
};
If that fixes it, the theory holds.
(Aside...)
For what it's worth, making your template require a backbone model instance instead of plain data is probably inferior, so consider just having your template do <%= member.photo_profile %> instead so it doesn't care where the data comes from. This also makes it easier to use the presenter design pattern. You can use member.toJSON() in your view to get at the plain data attributes to pass in to the template.

Right way to do navigation with Ember

What's the "right way" (or at least the options, if there is no single "Ember way" of doing this) for a navigation sidebar? Should I be looking at ContainerViews somehow, or should I just use the new outlet feature and stick the navigation inside my application view?
In addition, what's the "right way" to set an .active class on an li depending on the URL (I'm using routing)? Is there some kind of a helper for this?
<Update date="2013-01-16">
The previous examples are no longer valid since the recent changes in the Router API, so I'm not going to fix those. All applications using the old router should migrate as soon as possible to the latest.
Here's an updated fiddle:
Source |
Live Demo
I will be maintaining/fixing/adding features every so often.
Edit on Apr 3rd 2013:
Alternative Sample - WIP: source | demo
ALL CONTENT BELOW IS DEPRECATED
<Update>
2012-Nov-09
Just adding a link to a better sample that also addresses the part which the OP wants to set a class in the current navbar item when a given route is selected
Source in JSFiddle (Click here to see it running)
If you look in the NavigationController you'll see the 'selected' property, which I use to check in the isActive method of the child view NavigationItemView. The isActive will return true or false based on the value in the menu property of the same view (defined in the template) and the value in the property selected (of the controller). Then check the classNameBinding expressions which either sets 'active' or nothing to the class of that particular child.
Also check the ConnectOutlets which is where I'm marking that nav item as selected.
This is running on ember-latest.
I'm also using a little of Ember.Bootstrap as well as some of the original Twitter Bootstrap features/classes/etc (but I've replaced the styles with metro-bootstrap).
Not pasting the whole thing here because of space and all. I will leave the original code and link to the same for reference to the original question/answer.
I'll keep updating this new sample just because ember is fun =)
</Update>
This fiddle shows a static navbar from a view, and the outlet is used only for content display, or you can go directly to the display to see it running
As you can see, you can use a simple view containing your action links and have this view rendered in you application main view. The sub-routes under "starting" also have a mini navbar, coming from a similar template.
Handlebars:
<script type="text/x-handlebars" data-template-name="application">
<h1>My Ember Application</h1>
{{view App.NavbarView controllerBinding="controller.controllers.navbarController"}}
<br /><hr />
<div class="content">
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="navbar">
<ul>
<li><a href="#" {{action gotoHome}}>Home</a></li>
<li><a href="#" {{action gotoStarting}}>Getting Started</a></li>
<li><a href="#" {{action gotoCommunity}}>Community</a></li>
</ul>
</script>
<script type="text/x-handlebars" data-template-name="getting-started-menu">
<ul>
<li><a href="#" {{action gotoIndex}}>Overview</a></li>
<li><a href="#" {{action gotoMVC}}>About MVC</a></li>
<li><a href="#" {{action gotoEmber}}>About Ember</a></li>
</ul>
</script>
<script type="text/x-handlebars" data-template-name="home">
<h2>Welcome</h2>
<br />
<img src="http://emberjs.com/images/about/ember-productivity-sm.png" alt="ember logo" />
<br />
<br />
<p>Bacon ipsum dolor sit amet qui ullamco exercitation, shankle beef sed bacon ground round kielbasa in. Prosciutto pig bresaola, qui meatloaf ea tongue non dolore et pork belly andouille ribeye spare ribs enim. Enim exercitation elit, brisket nisi ex swine in jerky consequat pastrami dolore sed ad. In drumstick cow, salami swine fatback short ribs ham ut in shankle consequat corned beef id. Deserunt prosciutto beef speck. Sirloin incididunt kielbasa excepteur irure.</p>
<p>Do beef ribs dolore swine chicken shankle, venison officia qui magna ea anim. Jerky shank shankle, tongue in pork loin commodo boudin elit cupidatat turducken id capicola meatball. Strip steak ham hock tenderloin, id chicken drumstick sint jerky. Dolore veniam cillum minim, pariatur est beef. Sunt fatback tri-tip ex chuck.</p>
<br />
<br />
<strong>Note</strong>: This is a basic template with no <i>bindings</i>
</script>
<script type="text/x-handlebars" data-template-name="starting">
<h2>Getting Started with Ember</h2>
{{view App.StartingMenuView}}
<br />
<br />
<br />
<p>Bacon ipsum dolor sit amet qui ullamco exercitation, shankle beef sed bacon ground round kielbasa in. Prosciutto pig bresaola, qui meatloaf ea tongue non dolore et pork belly andouille ribeye spare ribs enim. Enim exercitation elit, brisket nisi ex swine in jerky consequat pastrami dolore sed ad. In drumstick cow, salami swine fatback short ribs ham ut in shankle consequat corned beef id. Deserunt prosciutto beef speck. Sirloin incididunt kielbasa excepteur irure.</p>
<p>Do beef ribs dolore swine chicken shankle, venison officia qui magna ea anim. Jerky shank shankle, tongue in pork loin commodo boudin elit cupidatat turducken id capicola meatball. Strip steak ham hock tenderloin, id chicken drumstick sint jerky. Dolore veniam cillum minim, pariatur est beef. Sunt fatback tri-tip ex chuck.</p>
<br />
<br />
<strong>Note</strong>: This is a basic template has a menu view embedded
</script>
<script type="text/x-handlebars" data-template-name="about-mvc">
<h2>About MVC</h2>
{{view App.StartingMenuView}}
<br /><br />
<br /><p>
Model–View–Controller (MVC) is a software design for interactive computer user interfaces that separates the representation of information from the user's interaction with it.[1][8] The model consists of application data and business rules, and the controller mediates input, converting it to commands for the model or view.[3] A view can be any output representation of data, such as a chart or a diagram. Multiple views of the same data are possible, such as a pie chart for management and a tabular view for accountants.
</p>
Read more at Wikipedia
<br />
<br />
<strong>Note</strong>: This is a basic template has a menu view embedded
</script>
<script type="text/x-handlebars" data-template-name="about-ember">
<h2>About Ember</h2>
{{view App.StartingMenuView}}
<br /><br />
<br />
<p>A framework for creating <strong>ambitious</strong> web applications</p>
Read more at emberjs.com
<br />
<br />
<p>Bacon ipsum dolor sit amet qui ullamco exercitation, shankle beef sed bacon ground round kielbasa in. Prosciutto pig bresaola, qui meatloaf ea tongue non dolore et pork belly andouille ribeye spare ribs enim. Enim exercitation elit, brisket nisi ex swine in jerky consequat pastrami dolore sed ad. In drumstick cow, salami swine fatback short ribs ham ut in shankle consequat corned beef id. Deserunt prosciutto beef speck. Sirloin incididunt kielbasa excepteur irure.</p>
<p>Do beef ribs dolore swine chicken shankle, venison officia qui magna ea anim. Jerky shank shankle, tongue in pork loin commodo boudin elit cupidatat turducken id capicola meatball. Strip steak ham hock tenderloin, id chicken drumstick sint jerky. Dolore veniam cillum minim, pariatur est beef. Sunt fatback tri-tip ex chuck.</p><br />
<br />
<strong>Note</strong>: This is a basic template has a menu view embedded
</script>
<script type="text/x-handlebars" data-template-name="community">
<h1>Ember Community</h1>
<p>
Get in touch with the community
</p>
<p>Featured contact info:</p>
{{#each item in content}}
<a {{bindAttr href="item.linkUrl" }} target="_blank">
<img height="32" width="32" {{bindAttr src="item.imageUrl" title="item.displayName" alt="item.displayName"}} /><br />
{{item.displayName}}
</a><br />
{{/each}}
<br />
Check more information about ember community at emberjs.com
<br />
<br />
<strong>Note</strong>: This is a template with a <i>foreach</i> type of loop
</script>​
JavaScript:
App = Em.Application.create();
App.ApplicationController = Em.Controller.extend();
App.ApplicationView = Em.View.extend({
templateName: 'application'
});
App.HomeController = Em.Controller.extend();
App.HomeView = Em.View.extend({
templateName: 'home'
});
App.NavbarController = Em.Controller.extend();
App.NavbarView = Em.View.extend({
templateName: 'navbar'
});
App.StartingController = Em.Controller.extend();
App.StartingView = Em.View.extend({
templateName: 'starting'
});
App.StartingMenuController = Em.Controller.extend();
App.StartingMenuView = Em.View.extend({
templateName: 'getting-started-menu'
});
App.AboutMVCController = Em.Controller.extend();
App.AboutMVCView = Em.View.extend({
templateName: 'about-mvc'
});
App.AboutEmberController = Em.Controller.extend();
App.AboutEmberView = Em.View.extend({
templateName: 'about-ember'
});
App.CommunityModel = Em.Object.extend({
displayName: null,
linkUrl: null,
imageUrl: null
});
App.CommunityController = Em.ArrayController.extend({
content: [],
init: function() {
this._super();
this.pushObject(
App.CommunityModel.create({
displayName: 'Twitter',
linkUrl: 'https://twitter.com/#!/emberjs',
imageUrl: 'http://icons.iconarchive.com/icons/iconshots/social-media-network/32/twitter-icon.png'
}));
this.pushObject(
App.CommunityModel.create({
displayName: 'GitHub',
linkUrl: 'https://github.com/emberjs/ember.js',
imageUrl: 'http://www.workinprogress.ca/wp-content/uploads/github.png'
}));
}
});
App.CommunityView = Em.View.extend({
templateName: 'community',
contentBinding: 'App.CommunityController.content'
});
App.Router = Em.Router.extend({
enableLogging: true,
location: 'hash',
root: Em.Route.extend({
// EVENTS
gotoHome: Ember.Route.transitionTo('home'),
gotoStarting: Ember.Route.transitionTo('starting.index'),
gotoCommunity: Ember.Route.transitionTo('community.index'),
// STATES
home: Em.Route.extend({
route: '/',
connectOutlets: function(router, context) {
router.get('applicationController').connectOutlet('home');
}
}),
starting: Em.Route.extend({
// SETUP
route: '/starting',
connectOutlets: function(router, context) {
router.get('applicationController').connectOutlet('starting');
},
// EVENTS
gotoMVC: Ember.Route.transitionTo('mvc'),
gotoEmber: Ember.Route.transitionTo('ember'),
gotoIndex: Ember.Route.transitionTo('index'),
// STATES
index: Em.Route.extend({
route: '/',
connectOutlets: function(router, context) {
router.get('applicationController').connectOutlet('starting');
}
}),
mvc: Em.Route.extend({
route: '/mvc',
connectOutlets: function(router, context) {
router.get('applicationController').connectOutlet('aboutMVC');
}
}),
ember: Em.Route.extend({
route: '/ember',
connectOutlets: function(router, context) {
router.get('applicationController').connectOutlet('aboutEmber');
}
})
}),
community: Em.Route.extend({
// SETUP
route: '/community',
connectOutlets: function(router, context) {
router.get('applicationController').connectOutlet('community');
},
// EVENTS
// STATES
index: Em.Route.extend({
route: '/',
connectOutlets: function(router, context) {
router.get('applicationController').connectOutlet('community');
}
})
})
})
});
App.initialize();​
I didn't like MilkyWayJoe's answer because if you sooner or later want to change the naming of your states or whatever you have to go through the code AND the view as well, also adding a function to transitionTo every route seems not desirable.
My approach is a bit more programmatic and modularized:
# Parent View-Tamplate, holding the navbar DOM elements
App.NavView = Ember.View.extend(
controller: App.NavArrayController
templateName: "ember-nav"
)
# We push NavItems into this array
App.NavArrayController = Ember.ArrayController.create(
content: Ember.A([])
)
# NavItem has two settable properties and
# an programmatic active state depending on the router
App.NavItem = Ember.Object.extend(
title: ''
goto: null # <=this is the name of the state we want to go to!
active: (->
if App.router.currentState.name == #.get "goto"
true
else
false
).property('App.router.currentState.name').cacheable()
)
# the actual NavElement which gets the class="active" if the
# property "active" is true, plus a on-click binding to
# make the Router transition to this state
App.NavItemView = Ember.View.extend(
tagName: "li"
classNameBindings: ["active"]
click: ->
App.router.transitionTo(#get('goto'))
false
)
nav-view.hbs (for twitter-bootstrap-style navs)
<div class="nav-collapse collapse">
<ul class="nav">
{{#each App.NavArrayController}}
{{#view App.NavItemView classBinding="active" gotoBinding="goto"}}
<a href="#" {{bindAttr data-goto="goto"}}> {{title}}</a>
{{/view}}
{{/each}}
</ul>
</div>
This way, I can just create and mess around with my routes in the Router,
and keep the Nav-Definitions side-by-side:
# put this somewhere close to the Router
App.NavArrayController.pushObjects(
[
App.NavItem.create(
title: 'Home'
goto: 'home'
),
App.NavItem.create(
title: 'Chat'
goto: 'chat'
),
App.NavItem.create(
title: 'Test'
goto: 'test'
)
]
)