What is the cleanest way to get <li class="active"> for the active page in the following Ember app?
index.html
<script type="text/x-handlebars">
<ul class="nav">
<li>{{#linkTo 'ping'}}Ping{{/linkTo}}</li>
<li>{{#linkTo 'pong'}}Pong{{/linkTo}}</li>
</ul>
</script>
app.js
App = Ember.Application.create()
App.Router.map(function() {
this.route("ping", { path: "/ping" });
this.route("pong", { path: "/pong" });
});
This workaround did it for me:
{{#linkTo 'menus.search' tagName='li' href=false}}
{{#linkTo 'menus.search'}}
<i class="icon-search"></i>
{{/linkTo}}
{{/linkTo}}
It creates an li element containing an anchor element. And both will be updated with the "active" class when the route is active.
replace in your template the li tags like so:
index.html
<script type="text/x-handlebars">
<ul class="nav">
{{#linkTo 'ping' tagName="li"}}Ping{{/linkTo}}
{{#linkTo 'pong' tagName="li"}}Pong{{/linkTo}}
</ul>
</script>
the {{linkTo}} with the tagName specified will apply a css class name of 'active' automatically when the application's current route matches the supplied route name.
example, when your app url is at /#/ping the resulting markup would be something like:
...
<li class="active">Ping</li>
...
Or you create a custom view
App.ItemView = Ember.View.extend({
tagName: 'li',
classNameBindings: ['active'],
active: function() {
return this.get('childViews.firstObject.active');
}.property()
});
and then use it like so
<script type="text/x-handlebars">
<ul class="nav">
{{#view App.ItemView}}
{{#linkTo 'ping'}}Ping{{/linkTo}}
{{/view}}
{{#view App.ItemView}}
{{#linkTo 'pong'}}Pong{{/linkTo}}
{{/view}}
</ul>
</script>
some css to see it actually working
li a {
color: #000;
}
li a.active {
color: #f00;
}
hope it helps
Just nest the {{link-to}} with a tagName on the outer one. This will set an active class on both the outer <li> and the inner <a> tag.
{{#link-to "ping" tagName="li"}}
{{#link-to "ping"}}ping{{/link-to}}
{{/link-to}}
{{#link-to "pong" tagName="li"}}
{{#link-to "pong"}}pong{{/link-to}}
{{/link-to}}
Related
I'm trying to do a list of product items and make them so when you click the image or title it will show a single page/template with the more info, etc.
But, when ever I use {{#each product in model}} the link-to just returns an undefined.
Heres what I have
App.Router.map(function(){
this.route('about', { path: '/aboutus' } );
this.resource('products');
this.resource('product', { path: '/products/:title' } );
this.resource('contacts');
});
App.ProductsRoute = Ember.Route.extend ({
model: function(){
return App.PRODUCTS;
}
});
// Logging out Params from the Route
App.ProductRoute = Ember.Route.extend ({
model: function(params){
return App.PRODUCTS.findBy('title', params.title);
}
});
App.PRODUCTS = [
{
title: 'Flint',
price: 99,
description: 'Flint is a hard, sedimentary cryptocrystalline form of the mineral quartz, categorized as a variety of chert.',
isOnSale: true,
image: 'images/flint.png'
},
{
title: 'Kindling',
price: 249,
description: 'Easily combustible small sticks or twigs used for starting a fire.',
isOnSale: false,
image: 'images/kindling.png'
}
];
when I use this method {{#each product in model}} i get undefined
<script type='text/x-handlebars' data-template-name='products'>
<h1>Products</h1>
<ul class="list-unstyled col-md-8">
{{#each product in model}}
<li class='row m-b'>
{{#link-to 'product' this }}<img {{bind-attr src='product.image'}} class='img-thumbnail col-md-5' alt='product-image' />{{/link-to}}
<div class="col-md-7">
<h2>{{product.title}}</h2>
<p class="product-description">{{product.description}}</p>
<p><button class="btn btn-success">Buy for ${{product.price}}</button></p>
</div>
</li>
{{/each}}
</ul>
</script>
<script type='text/x-handlebars' data-template-name='product'>
<div class="row">
<div class="col-md-7">
<h2>{{title}}</h2>
<p>{{description}}</p>
<p>Buy for ${{price}}</p>
</div>
<div class="col-md-5">
<img {{bind-attr src='image'}} class='img-thumbnail img-rounded' />
</div>
</div>
</script>
but when I use just {{#each}} it returns normally BUT it warns me this: DEPRECATION: Using the context switching form of {{each}} is deprecated. Please use the keyword form ({{#each foo in bar}}) instead.
<script type='text/x-handlebars' data-template-name='products'>
<h1>Products</h1>
<ul class="list-unstyled col-md-8">
{{#each}}
<li class='row m-b'>
{{#link-to 'product' this }}<img {{bind-attr src='image'}} class='img-thumbnail col-md-5' alt='product-image' />{{/link-to}}
<div class="col-md-7">
<h2>{{title}}</h2>
<p class="product-description">{{description}}</p>
<p><button class="btn btn-success">Buy for ${{price}}</button></p>
</div>
</li>
{{/each}}
</ul>
</script>
which one should I use and how do I fix the undefined error? I'm guessing it has to do with the App.ProductRoute but can't figure it out, still new to ember :l
You should use
{{#each product in model}}
and to fix your undefined use the following:
{{#link-to 'product' product }} ...title... {{/link-to}}
When you use {{#each}} the context of this gets switched to each item in the loop, which is sometimes confusing and is being deprecated. When you use the {{#each product in model}} version, the context of each item through the loop is product and this remains whatever it was you entered each
Hi i try to make an simple ember app that's get info form a json file. App is located here:http://www.autoroben.nl/m/. Problem is i need the ember view return back an id (from the li element) which i need for handlebars. so i can pop up car info with the same jsonfile as the car list.
// MODAL
App.OpenModal = Ember.View.extend({
click: function(evt) {
var id = $(".lijst li").attr('id');
alert(id)
$('#modal').addClass('active');
}
});
the template
<script type="text/x-handlebars" id="index">
<header class="bar bar-nav">
<h1 class="title">AUTOROBEN</h1>
</header>
<div class="content">
<ul class="table-view lijst">
{{#each}}
<li class="table-view-cell media" id="{{unbound ID}}">
{{#view App.OpenModal}}
<img src="/wp-content/uploads/{{unbound featured_image.attachment_meta.file}}" class="media-object pull-left" width="80">
{{title}}
<p>{{autoinfo.details.bouwjaar}} | {{autoinfo.details.kmstand}}</p>
{{/view}}
</li>
{{/each}}
</ul>
</div>
<div id="modal" class="modal">
<header class="bar bar-nav">
{{#view App.CloseModal}}
<a class="icon icon-close pull-right nostyle" href="#"></a>
{{/view}}
<h1 class="title">{{title}}</h1>
</header>
<div class="content">
<ul class="table-view">
<li class="table-view-divider">DETAILS</li>
<li class="table-view-cell">bouwjaar: {{autoinfo.details.bouwjaar}}</li>
<li class="table-view-cell">kmstand: {{autoinfo.details.kmstand}}</li>
</ul>
</div>
</div>
</script>
json file:
App.IndexRoute = Ember.Route.extend({
model: function() {
return Ember.$.getJSON('http://www.autoroben.nl/wp-json/posts/?type=autos');
}
});
Views in ember js by default get the parent context as its own context. In your case its the context of an single item in the each helper. You can access the ID from the view using the following code.
App.OpenModal = Ember.View.extend({
tagName: 'li',
classNames: ['table-view-cell', 'media'],
click: function(evt) {
alert(this.get('context.ID'));
$('#modal').addClass('active');
}
});
Here is a working bin.
I've got an ember app where my routing looks like this:
App.Router.map(function() {
this.resource('works', {path: '/works'}, function(){
this.route('work', {path:':work_id'})
});
});
I want to be able to link each of my work in my index template, for my naviguation. I tried this but it didn't work:
<script type="text/x-handlebars" data-template-name='application'>
<header id="header">
<nav id="main-nav" role="navigation">
<div class="item-container">
{{#link-to 'works' tagName='div' classNames="navItem work" }}
<p>Works</p>
{{/link-to}}
<ul>
{{#link-to 'work' works work}}{{work.title}}{{/link-to}}
</ul>
</div>
</nav>
</header>
<main id="main">
{{outlet}}
</main>
</script>
If you need more info just let me know.
Your index route definitions should look like this (assuming you are using Ember Data):
App.IndexRoute = Ember.Route.extend({
model: function() {
return this.store.find('work');
}
});
Then in your index template go through {{each}} of the App.Work records and link to the works.work route:
<ul>
{{#each}}
<li>{{#link-to 'works.work' this}}{{title}}{{/link-to}}</li>
{{/each}}
</ul>
When linking to a route, you do resource.route
{{#link-to 'works.work' work}}{{work.title}}{{/link-to}}
In this case I'm assuming work is a property that is a model, if not, you'll need to show your router.
I'm trying to use the Bootstap.Tabs component to create some bootstrap tabs.
I've declared the tabs as follows:
{{view Bootstrap.Tabs
contentBinding="App.tabsContent"
selectionBinding="App.selection"}}
And I'm using the following code to set up the content for the tabs.
App.ready = function() {
App.tabsContent= Ember.A([{value: "cred_app.associate_clients", title: "Associate clients"}, {value: "cred_app.facilities", title: "Facilities"}]);
};
Using this I can successfully render the bootstrap tabs.. and the route name pops up in App.selection.
I just don't understand how to get the links working, so that controller will transition to the route. I'd also like to get the active tab get the correct css applied to it so that the tabs show which route is currently being displayed.
UPDATE:
I have implemented this using a more simplistic approach:
<ul class='nav-tabs'>
{{#linkTo 'cred_app.associate_clients' model tagName='li' href=false}}
{{#linkTo 'cred_app.associate_clients' model}}Client Hierachy{{/linkTo}}
{{/linkTo}}
</ul>
You can do something like this:
(using my derived Bootstrap.Tabs implementation)
{{#view Bootstrap.TabContainerView currentView="patient"}}
<ul class="nav nav-tabs">
{{#view Bootstrap.TabView value="patient"}}<a>Patient</a>{{/view}}
{{#view Bootstrap.TabView value="visits"}}<a>Visits</a>{{/view}}
{{#view Bootstrap.TabView value="contacts"}}<a>Contacts</a>{{/view}}
{{#view Bootstrap.TabView value="sessions"}}<a>Sessions</a>{{/view}}
</ul>
{{#view Bootstrap.TabPaneView viewName="patient"}}
{{render "patient"}}
{{/view}}
{{#view Bootstrap.TabPaneView viewName="visits"}}
{{render "visits"}}
{{/view}}
{{#view Bootstrap.TabPaneView viewName="contacts"}}
{{render "contacts"}}
{{/view}}
{{#view Bootstrap.TabPaneView viewName="sessions"}}
{{render "sessions"}}
{{/view}}
{{/view}}
or using the router:
<ul class="nav nav-tabs">
{{#view Bootstrap.TabItem item="patient"}}
{{#linkTo "tab.patient" content}}Patient{{/linkTo}}
{{/view}}
{{#view Bootstrap.TabItem item="visits"}}
{{#linkTo "tab.visits" content}}Visits{{/linkTo}}
{{/view}}
{{#view Bootstrap.TabItem item="contacts"}}
{{#linkTo "tab.contacts" content}}Contacts{{/linkTo}}
{{/view}}
{{#view Bootstrap.TabItem item="sessions"}}
{{#linkTo "tab.sessions" content}}Sessions{{/linkTo}}
{{/view}}
</ul>
{{outlet}}
the magic is done by the Bootstrap.TabItem, it gets the active state from the linkTo helper
Bootstrap.TabItem = Ember.View.extend({
tagName: 'li',
classNameBindings: ['active'],
activeChanged: function () {
var self = this;
Ember.run.next(this, function () { //delay
if (!self.isDestroyed) {
self.set('active', self.get('childViews.firstObject.active'));
}
});
}.observes('childViews.firstObject.active') //get the active state from the linkTo helper
});
now you only need a router, something like this:
App.Router.map(function (match) {
...
this.resource('tab', { path: '/tab' }, function () {
this.route('patient');
this.route('visits');
this.route('contacts');
this.route('sessions');
});
...
});
a jsFiddle might help
Please look at Bootstrap for Ember
It fully supports Pills & Tabs:
https://github.com/ember-addons/bootstrap-for-ember
Showcase: ember-addons.github.io/bootstrap-for-ember
I'm trying to use multiple named outlets with Ember.js. Is my approach below correct?
Markup:
<script type="text/x-handlebars" data-template-name="application">
<div id="mainArea">
{{outlet main_area}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="home">
<ul id="sections">
{{outlet sections}}
</ul>
<ul id="categories">
{{outlet categories}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="sections">
{{#each section in controller}}
<li><img {{bindAttr src="section.image"}}></li>
{{/each}}
</script>
<script type="text/x-handlebars" data-template-name="categories">
{{#each category in controller}}
<img {{bindAttr src="category.image"}}>
{{/each}}
</script>
JS Code:
Here I set the content of the various controllers to data grabbed from a server and connect outlets with their corresponding views. Since the HomeController has no content, set its content to an empty object - a hack to get the rid of this error message:
Uncaught Error: assertion failed: Cannot delegate set('categories'
) to the 'content' property of object
proxy : its 'content' is undefined.
App.Router = Ember.Router.extend({
enableLogging: false,
root: Ember.Route.extend({
index: Ember.Route.extend({
route: '/',
connectOutlets: function(router){
router.get('sectionsController').set('content',App.Section.find());
router.get('categoriesController').set('content', App.Category.find());
router.get('applicationController').connectOutlet('main_area', 'home');
router.get('homeController').connectOutlet('home', {});
router.get('homeController').connectOutlet('categories', 'categories');
router.get('homeController').connectOutlet('sections', 'sections');
}
})
})
});
If it's any help, I got this error because I was connecting to an Ember.ObjectController instead of Ember.Controller.