I have the following code for generating links to objects and I have a template that renders it but I would like to have each item in the list call either a different template or display different items. Is this possible?
<div class="main-content container">
<div class="container-fluid">
<div class="col-xs-3">
<div class="span3">
<table class='table'>
<thead>
<tr><th><h3>Select Your Source</h3></th></tr>
{{#each refRecord in model}}
<tr><td>
{{#link-to 'ref' refRecord classNames="fullwidth"}}{{refRecord.type}}{{/link-to}}
</td></tr>
{{/each}}
</table>
</div>
</div>
<div class="col-xs-9">
{{outlet}}
</div>
</div>
</div>
I'm not sure if I've understood correctly, but I took your question in two ways, either they link to a different template, or they render each item different in the list.
Link to different templates
You can create dynamic link-to using a property instead of a string in the link-to statement.
<ul>
{{#each item in model}}
<li>{{#link-to item.template item}}{{item.color}}{{/link-to}}</li>
{{/each}}
</ul>
http://emberjs.jsbin.com/xarixiyu/1/edit
Render each item different
This is a bit different since render doesn't allow taking a property and resolving the name dynamically. But you can still use an if statement and render different items differently.
{{#each item in model}}
<li>
{{#if item.foo}}
{{render 'foo' item}}
{{/if}}
{{#if item.bar}}
{{render 'bar' item}}
{{/if}}
</li>
{{/each}}
http://emberjs.jsbin.com/xarixiyu/2/edit
Related
Why while this code does render,
{{#if ordered}}
<ol>
{{#each things as |thing|}}
<li {{action "showThing" thing}}>{{thing}}</li>
{{/each}}
</ol>
{{else}}
<ul>
{{#each things as |thing|}}
<li {{action "showThing" thing}}>{{thing}}</li>
{{/each}}
</ul>
{{/if}}
this does not?
{{{if ordered "<ol>" "<ul>"}}}
{{#each things as |thing|}}
<li {{action "showThing" thing}}>{{thing}}</li>
{{/each}}
{{{if ordered "</ol>" "</ul>"}}}
The last snippet emits <ol></ol> before the list and no closing tag after the list:
<div id="ember260" class="ember-view"><h2>Ordered List Of Things</h2>
<ol></ol>
<li data-ember-action="" data-ember-action-261="261">yarn</li>
<li data-ember-action="" data-ember-action-262="262">feathers</li>
<li data-ember-action="" data-ember-action-263="263">dinner plate</li>
<li data-ember-action="" data-ember-action-264="264">sheep</li>
</div>
and why does this code not even compile?
{{#if ordered}}
<ol>
{{else}}
<ul>
{{/if}}
{{#each things as |thing|}}
<li {{action "showThing" thing}}>{{thing}}</li>
{{/each}}
{{#if ordered}}
</ol>
{{else}}
</ul>
{{/if}}
Error:
Unclosed element ol (on line 2).
I am writing the code what PatsyIssa mentioned in his comments,
Create component named ordered-list.
{{ordered-list tagName=(if (eq ordered 'ol' 'ul')) things=things showThings=(action 'showThings')}}
In ordered-list.hbs,
{{#each things as |thing|}}
<li {{action showThing thing}}>{{thing}}</li>
{{/each}}
For the eq helper you need to install ember-truth-helpers addon or create your own helper that simply compares values.
I'm trying to access data two times in my template, once on a list view, and once in a modal view. Upon clicking on the image, the modal will display a lot of the same data, just blown up. I'm having issues. The modal seems to be taking the last set of data, even though it's nested in the each statement. Any ideas? Here's my code...
<div class="row">
{{#each model.products as |product|}}
<div class="col-xs-12 col-sm-6 col-md-4">
<div class="shopify-grid-wrapper">
<div id="#image-wrapper" class="image-wrapper" {{action 'openModal'}}>
<div class="img-overlay">
<p>
Click for More Details
</p>
</div>
{{#each product.images as |image|}}
<img src= {{image.src}} />
{{/each}}
</div>
<div class="description-wrapper">
<span><p>{{product.title}}</p></span>
<p>
{{product.productType}}
</p>
<p>
{{product.tags}}
</p>
</div>
</div>
</div>
{{#if shopifyModal}}
{{#liquid-wormhole class="fullscreen-modal" }}
<div class="left-side">
{{selectedProduct.title}}
</div>
<div class="right-side">
{{buy-button product=product.attrs open="openCart"}}
<div class="Cart {{if model.isCartOpen "Cart--open"}}">
{{shopify-cart close="closeCart"}}
</div>
<p {{action 'closeModal'}}>
Close
</p>
</div>
{{/liquid-wormhole}}
{{/if}}
{{/each}}
</div>
The problem was answered in the comments, but I'm adding this here in case someone finds it.
When looping over a collection in a template, if you have an action inside that loop, you must pass some information to the action handler if you expect the "current" item to be processed by the action handler, like this:
{{action 'openModal' product}}
I have normal, basic ember-cli project.
This is my application.hbs:
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
{{render 'sidebar'}}
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
{{outlet}}
</div>
</div>
</div>
This is my post.hbs:
{{#each model as |post|}}
{{post.text}}
{{/each}}
This is my sidebar.hbs:
<ul class="nav nav-sidebar">
{{#each model.posts as |post|}}
<li>{{#link-to author}}{{post.author.name}}{{/link-to}}</li>
{{/each}}
</ul>
and everything else is standard.
How to make work {{render 'sidebar'}} with just the title of my categories?
Now it shows nothing.
Updated the answer above me.
// application.hbs
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
{{side-bar}}
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
{{outlet}}
</div>
</div>
</div>
// templates/components/side-bar.hbs
<ul class="nav nav-sidebar">
{{#each posts as |post|}}
<li>{{#link-to author}}{{post.author.name}}{{/link-to}}</li>
{{/each}}
</ul>
// components/side-bar.js
// This triggers once the component is called out {{side-bar}}.
init: function() {
// You're extending ember component class here
// This class has its own init function if u dont call
// _super() it means that the component has not yet been
// Initialised and component's not working.
this._super();
// Use your queries or what ever u need here
// e.g query('posts', { user: 1 })
this.set('posts', this.get('store').find(x));
}
I'm not sure why the render helper was not deprecated in Ember 1.13 and removed in 2.0, but you really shouldn't use it any more. The render helper uses a view and a controller that is not at the top level. Views have been removed in 2.0, and controllers not at the top level are deprecated.
Make your sidebar a component.
// application.hbs
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
{{side-bar model=model}}
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
{{outlet}}
</div>
</div>
</div>
// templates/components/side-bar.hbs
<ul class="nav nav-sidebar">
{{#each model.posts as |post|}}
<li>{{#link-to author}}{{post.author.name}}{{/link-to}}</li>
{{/each}}
</ul>
Today , I just start learning ember.js. I tried one sample application.
Search the result and it will show the list. Click on the link and it will show the result at right sidebar. It's working fine.
However, I want to show home template at first.
When I tried with {{outlet name}} , it can show the home template however it is not working when I click on link. So, is there any way to show default outlet ?
I found about default outlet at here . However, it need to remove my data-templte-name to show default outlet. I don't want to remove the data-template-name.
Current template is like following.
<script type="text/x-handlebars" data-template-name="dictionary">
<div id="left">
<header>
<div id="topheader">
<img src="images/logo.jpg" class="logo">
<i id="search-icon"> </i>
{{input type="text" id="query" placeholder="Search" value=query
action="query"}}
</div>
</header>
<div id="results">
{{#each results}}
{{#link-to "detail" this}}
<section>
<div class='detail'>
<div class='word'>{{Word}}</div>
<div class='state'>{{state}}</div>
<div class='def'>{{def}}</div>
</div>
</section>
{{/link-to}}
{{/each}}
</div>
<footer>
<div id="bottom">
<a href="#" class='btn'>Login</a>
<a href="#" class='btn add'>Add</a>
</div>
</footer>
</div>
<div id="right">
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" id="detail">
<div id="details">
<div class='word'>{{Word}}</div>
<div class='state'>{{state}}</div>
<div class='def'>{{def}}</div>
</div>
<div id="discuss">
</div>
</script>
<script type="text/x-handlebars" id="home">
<div id="homeScreen">
Sample home screen
</div>
</script>
The root template to be rendered is the application template (associated with the root/application level). An empty id/data-template-name is assumed to be the application template. If you want to use a different template for the application root you can create the application view and specify the templateName.
App.ApplicationView = Ember.View.extend({
templateName: 'foo'
});
http://emberjs.jsbin.com/EZocURAR/1/edit
Suppose I have the following partial template:
<script type="text/x-handlebars" data-template-name="_folderList">
<table id="folder-list">
<thead>
<tr class="PLEASE_MAKE_ME_ACTIVE_IF_SELECTED_ROW">
<th>Name</th>
<th>Date Created</th>
</tr>
</thead>
<tbody>
{{#each folder in controller}}
<tr>
<td>
{{#linkTo "folder" folder }}
<i class="icon-folder-close"></i> {{ folder.folder_name }}
{{/linkTo}}
</td>
<td style="padding-left: 15px;">
{{ prettyDate folder.created_date}}
</td>
</tr>
{{/each}}
</tbody>
</table>
</script>
Notice the class I've added to the table row element. How can I add an "active" class to this row when it's child link is the active link? Ember automatically adds the active link when the current route matches the element in the collection. I'm trying to find the elegant, "Ember way" of doing this without resorting to jQuery hacks.
While I'd still like to see an answer to the question as I originally stated it, the workaround I went with for now is not to use tables at all. I'm already using Bootstrap based CSS layouts for the rest of my site, so I decided to use a fluid layout instead of tables:
<script type="text/x-handlebars" data-template-name="_folderList">
<div id="folder-list">
<div class="container-fluid list-header">
<div class="row-fluid">
<div class="span5">Name</div>
<div class="span7">Date Created</div>
</div>
</div>
{{#each folder in controller}}
{{#linkTo "folder" folder }}
<div class="container-fluid list-item">
<div class="row-fluid">
<div class="span5">
<i class="icon-folder-close"></i> {{ folder.folder_name }}
</div>
<div class="span7">
{{ prettyDate folder.created_date}}
</div>
</div>
</div>
{{/linkTo}}
{{/each}}
</div>
</script>
This allows me to wrap the whole "row" with the anchor using {{#linkTo}} and style the whole row accordingly.
You can use bindAttr to toggle the classname. For example if you hold the state in an isSelected property in your controller then in the template.
<tr {{bindAttr class='isSelected:active'}}>
Where active is the css class name.