Here are my controllers:
App.DesignPhotosController = Ember.ArrayController.extend({
itemController: 'designPhoto'
});
App.DesignPhotoController = Ember.ObjectController.extend({
needs: ['designPhotos'],
toDelete: false,
actions: {
toggleDelete: function() {
this.set('toDelete', !this.get('toDelete'));
}
}
});
And my template:
{{#each}}
<ul>
<li>
{{title}}
{{#if toDelete}}
<button class="restore" {{action "toggleDelete"}}>Restore</button>
{{else}}
<button class="delete" {{action "toggleDelete"}}>Delete</button>
{{/if}}
</li>
</ul>
{{/each}}
However, when I click on the "Delete" button, I get a message logged:
Error: Nothing handled the action 'toggleDelete'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble.
As far as I can tell I am doing this correctly, bit I tried forcing it by various combinations of:
Adding target=this to the action
Adding {{#each item in controller}} and target=item
Changing the action to {{action toggleDelete this}}, with and without quotes
Nothing works.
Can anyone point out what I am doing wrong?
One possible reason of this behaviour is a bug present in 1.13 (up until the very last 1.x release, 1.13.13), which breaks actions that should be processed by item controllers.
In case you can't revert to release 1.12, the second workaround from the question
changing {{#each}} to {{#each item in controller}} and adding target=item to the action
is the officially recommended one and has worked for my code, although the first one
adding target=this to the action (with simple {{#each}})
should probably work too.
(I suspect that OP left either of these in the code and didn't register that it fixed the issue, because both came up as false negatives earlier due to Firefox's very persistent caching.)
Related
So I'm following a tutorial to build an app on CodeSchool and I was trying to figure out how to write in a toggle when I noticed an error in the console basically saying that nothing is handling the action block I wrote in the template.
"Nothing handled the action 'toggleOption model option'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble."
The code below is the part of the template I'm having trouble with.
<ul class='list list--answer'>
{{#each model.poll.option as |option|}}
<li class='list-item'>
<button class='list-item-checkbox {{if (eq model.option option) "is-selected"}}' {{action "toggleOption model option"}}>
<b class='srt'>Select</b>
</button>
<span>{{option.label}}</span>
</li>
{{/each}}
</ul>
This is the route associated with the template.
import Ember from 'ember';
export default Ember.Route.extend({
store: Ember.inject.service(),
model(){
const poll = this.modelFor('polls.poll');
return this.get('store').createVote(poll);
},
actions: {
toggleOption(vote,option){
vote.toggleOption(option);
}
}
});
Anyways, is there something I'm missing? I've been staring at this for awhile and I couldn't figure this out. The tutorial video I've been following and their completed code doesn't seem to run into this issue either.
There is syntax issue {{action "toggleOption model option"}} it should be {{action "toggleOption" model option}}.
I'm new to ember. I have a demo app working, and I'm moving towards making it look nice.
One issue I'm starting to grapple with is how to manipulate DOM elements. Coming from a server-side world, it's been pretty easy to just throw some jquery at stuff like this. Doesn't appear to be as straightforward in ember. But I'm probably missing something or approaching it wrong.
The immediate problem is: I have a list of 40-some <li> elements and I want to create a toggle to show/hide the list after the first 10 items.
I got something to work in my component like this:
import Ember from 'ember';
let $ = Ember.$;
export default Ember.Component.extend({
didInsertElement() {
this._super(...arguments);
Ember.run.scheduleOnce('afterRender', this, this.afterRenderEvent);
},
afterRenderEvent() {
let listTotal = $("#myList li").length;
$("#myList li").slice(10, listTotal).hide();
}
});
The problem is that when actions trigger and the view is re-rendered, afterRenderEvent() doesn't get called again, and the list shows in its entirety.
The above component corresponds to this template:
<ul id="myList">
{{#each aggs.categories as |category|}}
<li><a href="#" {{action (action add "filter_breadcrumb" category.key)}}>{{category.key}} ({{category.doc_count}})</a></li>
{{/each}}
</ul>
Is there a way to get around this? OR, is there a more "ember" way to approach this problem (and DOM manipulation in general)?
Introduce showCount property in controller and have action to set showCount to total list count.
import Ember from 'ember';
export default Ember.Component.extend({
showCount: 10,
actions: {
setShowCount(count) {
//you can set total count
this.set('showCount', count);
}
}
});
Install ember truth helpers addon or write computed property to check.
<ul id="myList">
{{#each aggs.categories as |category index|}}
<li style="{{if (gt index showCount) 'display:none'}}"><a href="#" {{action (action add "filter_breadcrumb" category.key)}}>{{category.key}} ({{category.doc_count}})</a></li>
{{/each}}
</ul>
If you don't want to display then you can just iterate just showCount aggs.categories alone by writing computed property or using ember-composable-helpers junk method
<ul id="myList">
{{#each (chunk showCount aggs.categories) as |category index|}}
<li><a href="#" {{action (action add "filter_breadcrumb" category.key)}}>{{category.key}} ({{category.doc_count}})</a></li>
{{/each}}
</ul>
Template:
{{#each document in documents}}
<div class="col-md-6" {{action "selectDocument" document}}>{{view Ember.Checkbox checked=document.isSelected}} {{document.name}}</div>
{{/each}}
Controller:
App.IndexDocumentsController = Ember.ArrayController.extend({
actions: {
selectDocument: function(document){
document.set('isSelected', !document.get('isSelected'));
}
}
});
When I click on the div, the checkbox toggles 'checked' property. But when I click on the ckeckbox - nothing happens. What can be the reason?
UPDATED
Link to jsbin: http://emberjs.jsbin.com/nuvocumuteto/1/edit?html,css,js,output
The issue is that when you click on the checkbox 2 things happen.
the checkbox toggles the isActive property, then
the selectRow action is ran which again toggles the isActive property
So the isActive property ends up staying in the same state that it was.
In your case I would get rid of the action, wrap the checkbox in a <label> and set the label to display: block.
The template would look like
<script type="text/x-handlebars" data-template-name="index">
<ul>
{{#each item in model}}
<li {{bind-attr class="item.isActive:active"}}><label>{{input type="checkbox" checked=item.isActive}}{{item.name}}</label></li>
{{/each}}
</ul>
</script>
and the css would look like
label {
display: block;
}
you would then be able to get rid of the selectRow action completely because clicking on the label will trigger the checkbox.
You can see a working bin here: http://emberjs.jsbin.com/nuvocumuteto/3/edit
I would argue that you are not following "The Ember Way" in two different ways here.
First, Ember.Checkbox is an internal Ember class (http://emberjs.com/api/classes/Ember.Checkbox.html). The recommended way to render a checkbox is to use the Handlebars input helpers (http://emberjs.com/guides/templates/input-helpers/#toc_checkboxes). This is just wrapping Ember.Checkbox anyway.
Second, if you want to update the value of isSelected, the "Ember Way" is to use two-way data bindings. Your code uses one-way data-binding when it reads document.isSelected and then tries to manually re-create the the data-binding in the other direction when the user clicks by manually writing a selectDocument action and calling it from an {{action}}.
Instead, simply bind the Ember Handlebars Input Helper directly to your value like this:
{{#each document in documents}}
<div class="col-md-6">{{input type="checkbox" checked=document.isSelected}} {{document.name}}</div>
{{/each}}
I have the need to load random items in my Ember application. To do this, I do the following:
Test.ApplicationRoute = Ember.Route.extend({
events: {
randomItem: function() {
var route = this;
$.getJSON('item/random.json', function(data) {
Test.Item.find(data).then(function(item) {
route.transitionTo('items.show', item);
});
});
}, // ..... etc
This works fine, except for one thing: nested-sideloaded data is not shown. When items.show is visited via a {{#linkTo 'items.show' item}}, the item's child data is also loaded and visible. However, when this randomItem event is fired, only the direct children are shown. The children of the children are not.
Why is this and/or how do I fix this?
It turns out, the reason the artifacts are not being shown is that I try to listen to controller.content.isLoaded to adapt the view to show a loading image if the content is still loading.
For some reason, the following shows the loading... text and icon forever on subsequent usages of the route:
{{#if controller.model.isLoaded}}
<div class="row">
</div>
{{#each artifact in controller}}
{{render "artifacts.show" artifact}}
{{else}}
<span class="muted">There are no artifacts.</span>
{{/each}}
{{else}}
<i class="icon-spin icon-spinner icon-large"></i> Loading...
{{/if}}
If anyone knows why, please let me know, so I can solve this problem.
In the "new" Ember.js (post Feb 15 2013), the old routes and transitions no longer work. I'm trying to figure out how to replace them. I've created a super-simple jdfiddle to illustrate what I currently have.
{{#each item in controller}}
<li><a {{action editDetails item}}> {{item.title}} </a></li>
{{/each}}
Each item has an ID, and this is successfully passed to editDetails() on the IndexController (click on one of the three hard-coded items in the output):
App.IndexController = Ember.ArrayController.extend({
editDetails: function(params){
console.log('details! ' + params.id);
}
});
Another template is waiting for a controller to show it and hand it the item for the details.... but nothing I have tried from this point works. So, how do I get these two hooked up together?
I updated your jsfiddle.
{{action}} helper are no longer used to transitioning between routes.
Now you must use the {{#linkTo}} helper.
{{#each item in controller}}
<li>{{#linkTo 'editDetails' item}}{{item.title}}{{/linkTo}}</li>
{{/each}}
Please take a look to the emberjs guides