Handlebars if statement issue - ember.js

{{#each this.data.roles as |role|}}
{{#if (eq role.name ( 'moderator' 'organizer'))}}
<div class="item">
{{role.name}}
</div>
{{/if}}
{{/each}}
It is only giving div with moderator only not with organizer

Welcome to Stack Overflow. Your helper invocation needs a slight tweak. I assume you need to show the div for both moderator and organizer role. So, the condition (in js) should be like,
role === "moderator" || role === "organizer"
the same can be translated into the handlebar expressions with the help of eq and or helpers like:
{{#each this.data.roles as |role|}}
{{#if (or (eq role.name "moderator") (eq role.name "organizer"))}}
<div class="item">
{{role.name}}
</div>
{{/if}}
{{/each}}

Related

ember if else conditionals

I have a conditional statement which contains a link. If something is true, the I'd like it to link to a 'place a' if it is not true I'd like it to link to 'place b'. But I am getting a build error.
I removed the conditional statement, and just have a normal link (link-to) ...so just a link to one place my code builds fine. The build error is just when I try to have 2 links. See below:
<div class="card text-xs-center">
{{if isShowingModal}}
{{#link-to 'place-a'}}
{{else}}
{{#link-to 'place-b'}}
{{/if}}
<div class="card-block">
<i class="fa fa-cogs" aria-hidden="true"></i>
</div>
<div class="card-block">
<h4 class="card-title">The Place</h4>
</div>
{{/link-to}}
</div>
The error says: Error: link-to doesn't match if - 8:19
application.js
export default Ember.Controller.extend({
isShowingModal: false,
actions: {
showNavMenu: function() {
this.toggleProperty('isShowingModal');
}
}
});
actually you are not ending link-to helper properly. it should end with {{/link-to}}
so in your case it will be
{{#link-to 'place-a' }} Place A {{\link-to}
{{#link-to 'place-b' }} Place B {{\link-to}
In your case complete code will be
<div class="card text-xs-center">
{{if isShowingModal}}
{{#link-to 'place-a' class='card-block fa fa-cogs'}}
The Place
{{/link-to}}
{{else}}
{{#link-to 'place-b' class='card-block fa fa-cogs'}}
The Place
{{/link-to}}
{{/if}}
</div>
For your help check it http://emberjs.com/api/classes/Ember.Templates.helpers.html#method_link-to
Yes this is because you haven't closed the link-to correctly. This will help you without duplicating your link-to statement.
<div class="card text-xs-center">
{{#link-to (if showingModal "place-a" "place-b") class='card-block fa fa-cogs'}}
<div class="card-block">
<i class="fa fa-cogs" aria-hidden="true"></i>
</div>
<div class="card-block">
<h4 class="card-title">The Place</h4>
</div>
{{/link-to}}
</div>

Link-to cannot find nested resource on passing two models

Here is the app i am learning to build.
categories has many products.
Accordion of category - heading and products as body is in categories template
router.js
MyApp.Router.map(function () {
this.resource('categories', {path: '/'}, function () {
this.resource('category', { path: '/:category_id'}, function () {
this.resource('product', {
path: '/:product_id'
});
});
});
});
My categories handlebar
<div class="panel-group" id="accordion1">
{{#each category in model}}
{{view MyApp.AccordionView context=category}}
{{/each}}
</div>
and my accordion view
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
{{#view MyApp.AccordionTitleView }}{{name}} {{/view}}
</h4>
</div>
<div {{bind-attr id=id}}class="panel-collapse collapse">
<div class="panel-body">
<table class="table">
<tbody>
{{#each products itemController="product"}}
<tr><td>{{#link-to 'category.product' category content }}{{content.name}}{{/link-to}}</td></tr>
{{/each}}
</tbody>
</table>
</div>
</div>
</div>
U P D A T E S
my issue got resolved by changing
{{#link-to 'category.product' category content }} in my accordion view to
{{#link-to product' category content }}
but as per ember guides
Ember guides
I can pass two model like this sample code
<p>
{{#link-to 'photo.comment' 5 primaryComment}}
Main Comment for the Next Photo
{{/link-to}}
</p>
i dont understand if its because my router hierarchy. but in any case i think it should give some nice error. I an a noob wonder what experts think on this
You have to use 'product' in your link-to instead of 'category.product'.
This is because in MyApp.Router.map() you made product a resource, not a route.
Resources' route names are unprefixed, whereas routes' route names are prefixed with their parent resource.
See http://emberjs.com/guides/routing/defining-your-routes/#toc_nested-resources

How to set itemController for instance variable in ember.js indexController?

I have a Ember.js page that displays a table of items and shows details of one of the items when it is selected. The controller looks like this:
CV.IndexController = Ember.ArrayController.extend({
itemController: "CurrVitae",
selectedCurrVitae: false,
actions: {
selectCurrVitae: function(currVitae) {
this.set('selectedCurrVitae', currVitae)
}
}
});
And the index controller is used in a template like this:
<div class="container">
<div class="curr-vitae-list">
{{#each curr_vitae in controller}}
<div class="curr-vitae-item row">
<div class="col-sm-2" {{action selectCurrVitae curr_vitae}}>
{{curr_vitae.name}}
</div>
<div class="col-sm-2">
<!-- NOTE: This method is defined on the item
controller (not the model) so the itemController is
available at this point. -->
{{curr_vitae.createdAtDisplay}}
</div>
<div class="col-sm-7">
<div class="embedded-cell">
{{curr_vitae.summary}}
</div>
<div class="embedded-cell">
{{curr_vitae.objective}}
</div>
</div>
</div>
{{/each}}
</div>
<div class="curr-vitae-view">
<h2>Details</h2>
<!-- EDIT: I have tried setting this
as {{#if selectedCurrVitae itemController="currVitae" }}
to match the way the #each handles item controllers but that did
not seem to work -->
{{#if selectedCurrVitae }}
<!-- NOTE: Down here, however, the item controller is not available
so I can't use methods defined on the item controller for the
currently selected instance. -->
{{ partial "cv_index_details" }}
{{/if}}
</div>
</div>
Question: The problem I'm running in to is that the itemController I've set in the index controller is not available when rendering the selectedCurrVitae in the cv_index_details.
More details:
Specifically, in the partial I want to reuse a editor component (taken from Noel Rappin's Ember.js book). So if the cv_index_details partial looks like this:
<h3 class="selected_cv">{{selectedCurrVitae.name}}</h3>
<div class="row selected_cv_summary">
<h4>Summary</h4>
{{block-editor emberObject=selectedCurrVitae propName="summary" action="itemChanged"}}
</div>
<div class="row selected_cv_experiences">
<h4>Experiences</h4>
{{#each experience in selectedCurrVitae.experiences itemController="experience"}}
{{ partial "experience_detail" }}
{{/each}}
</div>
So in this template, the itemChanged action is not found for the selectedCurrVitae instance. However, I use the same block-editor component for the experience instance and that works correctly; the itemChanged action defined on the ExperienceController is found.
selectedCurrVitae is outside of the itemController, the itemController is only applied inside the each (on each item, hence the name).
Probably the easiest way to accomplish this will be to reuse the item controller and use render.
Template
{{#if selectedCurrVitae }}
{{ render "cv_index_details" }}
{{/if}}
Controller
CV.CvIndexDetailsController = CV.CurrVitaeController.extend();
Or
Template
{{#if selectedCurrVitae }}
{{ render "currVitae" }}
{{/if}}
View
CV.CurrVitaeView = Ember.View.extend({
templateName: 'cv_index_details'
});

I can't loop an Object-Array with ember #each

<div class="nav-menu clearfix">
<ul class="list-unstyled list-inline">
{{#each MI in MB}}
<li id=""><span>{{ MI.MText }}</span></li>
{{else}}
{{MB}}
{{/each}}
</ul>
</div>
I want loop the MB with each.
but it dose not work and return the MB is empty.
but I get this for else.
[object Object],[object Object],[object Object],[object
Object],[object Object]
this is my route define
//application路由
App.ApplicationRoute = Ember.Route.extend(App.LazyLoadTemplate, {
model : function() {
return Ember.$.getJSON("/index/indexjson");
}
});
and get a json data is
{
'UIB':{...},
'MB':[{...},{...},...,{...}]
}
My English is not well ,Thanks for help!
As you already found, your scope of your property was incorrect. Just to set the record straight, Ember-Handlebars will not iterate over an object like it will over an Array. Additionally the else statement is totally legit, it will be triggered when the array being iterated across is empty (null/undefined/no elements)
{{#each item in model}}
{{item}}
{{else}}
No Items
{{/each}}
http://emberjs.jsbin.com/iWohUlE/1/edit
Edit as kingpin pointed out in his answer, this response is referencing the wrong version of handlebars.
Your misusing the block helper each in your template. Handlebars each will work similarly with objects and arrays. In addition you had an else outside of an if block. Rewrite your template as follows:
<div class="nav-menu clearfix">
<ul class="list-unstyled list-inline">
{{#each MB}}
<li id=""><span>{{ MText }}</span></li>
{{/each}}
</ul>
</div>
Fiddle example

Second argument (controller) to handlebars each helper. What does it mean?

I'm trying to analyse TodoMVC's Ember example. What does the second argument to the #each helper mean?
<ul id="todo-list">
{{#each filteredTodos itemController="todo"}}
<li {{bindAttr class="isCompleted:completed isEditing:editing"}}>
{{#if isEditing}}
{{view Todos.EditTodoView todoBinding="this"}}
{{else}}
{{view Ember.Checkbox checkedBinding="isCompleted" class="toggle"}}
<label {{action "editTodo" on="doubleClick"}}>{{title}}</label>
<button {{action "removeTodo"}} class="destroy"></button>
{{/if}}
</li>
{{/each}}
</ul>
It's supposed to be an option hash but I'm not sure.
It sets the itemController property of the current controller (TodosController I presume) to todo i.e the instance of the TodoController.
That means that every item (<li> element) will be binded not to the TodosController but to a TodoController instance.
isEditing looks for the property on the instance of TodoController and {{ action "removeTodo" }} will call removeTodo function on TodoController.