Ember CLI "Nothing Handled the Action" - javascript

I'm working through Ryan LaBouve's YouTube tutorial on building the TodoMVC app with Ember CLI. I'm about half way through, now adding a conditional within the template. When a (todo list) item is double-clicked, it is supposed to trigger a function editTodo that sets a property "isEditing" to true and replaces the text with an input box.
The doubleClick function is not working at all. It throws the following error in the console:
Uncaught Error: Nothing handled the action 'editTodo'. 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.
This is the relevant template section (todos.hbs):
<section id="main">
<ul id="todo-list">
{{#each todo in model itemComtroller="todo"}}
<li {{bind-attr class="todo.isCompleted:completed todo.isEditing:editing"}}>
{{#if todo.isEditing}}
<input class="edit">
{{else}}
{{input type="checkbox" class="toggle" checked=todo.isCompleted}}
<label {{action "editTodo" on="doubleClick"}}>{{todo.title}}</label><button class="destroy"></button>
{{/if}}
</li>
{{/each}}
</ul>
<input type="checkbox" id="toggle-all">
</section>
Here is the controller with the "editTodo" function (todo.js):
import Ember from 'ember';
export default Ember.ObjectController.extend({
actions: {
editTodo: function() {
this.set('isEditing', true);
}
},
isEditing: false,
isCompleted: function(key, value) {
var model = this.get('model');
if (value === undefined ) {
return model.get('isCompleted');
} else {
model.set('isCompleted', value);
model.save();
return value;
}
}.property('model.isCompleted')
});
I've cross-referenced my code with the video and the associated Github repo and still can't find the cause of the problem. There are also related issues on SO, but I've not seen one quite like this. Obviously I am new to Ember.js and can use all the help I can get.
THANKS!

It seems that you've run into a bug that was introduced in Ember 1.13.4. I'm not sure what it is, but it has to do with using an item controller and having an action in the loop. For now, you can downgrade to Ember 1.13.3 or lower to fix the issue. I will file a bug report so that this can be fixed in later versions of Ember.
Long term you won't be writing code like this. Item controllers have been completely removed in Ember 2.0, so you'll likely switch to using components for this type of situation when using Ember 2.0. For now you can practice using Ember 1.13.3.
Almost forgot:
Code that works in 1.13.3
Same code broken in 1.13.4
EDIT: Link to GitHub issue
EDIT2: It seems that some behavior has changed in Ember (possibly another bug?) between 1.12.0 and 1.13.0. For some reason the actions are no longer being caught in the item controller and instead are being sent directly to the route controller. I'm not 100% sure why that is, but as a fix you can either downgrade to Ember 1.12 or move your editTodo action to your todos controller instead.
EDIT3: Link to second Github issue
EDIT4: As suggested in the second bug ticket, you can also change the target of the action:
<label {{action "editTodo" on="doubleClick" target="todo"}}>{{todo.title}}</label>

Related

Upgrading materializecss from 0.100.1 to 1.0.0 results in multiple javascript errors

I'am trying to upgrade my materializecss from 0.100.1 to 1.0.0. I followed the upgrade guide and applied all the changes to my code but I am still facing multiple javascript errors. In our application we are using vue 2.6.10.
Tabs:
Our tabs are rendered by a vue component:
<ul class="tabs timerange" id="timeTab" style="width: 90%">
<input type="hidden" id="time" v-model="$parent.syncData.currentTime">
<li style="width:75px; display: inline-block" v-bind:data-time="value"
v-for="(value,key) in $parent.syncData.timeGrid"
class="tab">
<a class="text-black" v-bind:href="'#tab_'+key"
v-on:click="$parent.setTime(value)">{{value}} h</a>
</li>
</ul>
Then they get initialized in a separate javascript with jquery:
$(document).ready(function() {
$('#timeTab').tabs();
});
This results in the following error:
I've already tried initializing them in the created() and updated() callbacks of the vue component but without success.
Dropdown:
For dropdowns I get the following error:
This error is reproducible when I comment my code for the dropdown and replace it with the example code from the materializecss docs.
How can I fix these kind of errors or where is a good start to debug?
We had some duplicate initializations within the code. As well as some were initialized with jquery and some not. Cleaning up the initialization and only initializing the components once without jquery fixed the errors.
materializecss checks if already instances for the given elements exists and if they do they will be destroyed and reinitialized but within the destroy process we got the errors.

DOM Traversing Error in Safari - Ember.js

I have my template something like this,
<ul id="items">
{{#each items as |item index|}}
<li>
<!-- <input type="checkbox" id={{concat "pf" index}} /> -->
{{input type="checkbox" id=(concat "pf" index)}}
</li>
{{/each}}
</ul>
And I have my js something like this,
import Ember from "ember";
export default Ember.Controller.extend({
appName: "Ember Twiddle",
items: [{}],
init: function() {
$(document).on("click.somename", function (e) {
alert($(e.target).parent().length); //should get parent as "li" and length as 1
});
}
});
What happening for my project is that, if I click on ember input helper I am not able to get the parentElement using jQuery. But when I changed that input helper to normal <input type="checkbox" />, I am able to get the parentElement. I don't know whether Safari/Ember is using any virtual DOM or something to render its own helpers. This issue is happening only in Safari. In Chrome, it is working fine.
Unfortunately, I am not able to make a fiddle/plunker as the issue is not able to replicate in them. Sorry about that. In my project, I am using ember#2.7.3.
Any suggestions/help on this issue?
While I'd recommend trying to find a way to avoid using the jQuery click event in the first place, it sounds like an issue with how the different browsers treat parent. I would prefer to use .closest('li').eq(0) to access the first parent that matches the element you are looking for.

Im using ember with ember-modal-dialog package. Is there a way to pass a model into the close action cancelAlarmEdit?

{{#each alarms as |alarm|}}
{{if alarm.isEditing}}
{{#modal-dialog translucentOverlay=true close="cancelAlarmEdit"}}
//this works down here
<button type="btn btn-danger" {{action 'cancelAlarmEdit' alarm}}</button>
{{/modal-dialog}}
{{else}}
{{/if}}
{{/each}
Is there a way to pass a model into cancelAlarmEdit from the close tag above? I had trouble finding relevant info on it from https://github.com/yapplabs/ember-modal-dialog .
I'm pretty sure this should work:
{{#modal-dialog close=(action 'cancelAlarmEdit' alarm)}}
Actually the {{action}} helper is pretty similar to Javascripts bind.
I don't see such feature neither in docs, nor in the source code of this addon. You may try to create a new component, based on this addon's:
// app/components/modal-dialog.js
import ModalDialog from 'ember-modal-dialog/components/modal-dialog';
export default ModalDialog.extend({
actions: {
close() {
this.sendAction('close', this.get('closeParam'));
}
}
});
In template your should be able to pass closeParam attribute.
And if you will not succeed in extending, it's not that hard to write your own modal component.

How to adapt angular 2 code to use URIs with parameters

So far I've read https://angular.io/docs/ts/latest/guide/router.html#!#router-link and https://auth0.com/blog/2015/05/14/creating-your-first-real-world-angular-2-app-from-authentication-to-calling-an-api-and-everything-in-between/
but they're a bit too dense for my level and I'm getting lost easily.
So I thought about asking if there is a simpler way of doing what I want, or if there's another way of looking at the problem.
Currently I have "half" a webpage built
http://plnkr.co/edit/BcyPlw?p=preview
, in angular2, in which I use js and ts functions to get some D3 and some maps working:
<div layout="row" layout-wrap flex>
<div flex="50" *ngFor="#item of items">
<md-checkbox [checked]="exists(item, selected)" (click)="toggle(item, selected)">
{{ item }} <span *ngIf="exists(item, selected)">selected</span>
</md-checkbox>
</div>
</div>
The idea now is to add URIs to events such as: if you click calendar, trigger an event so that I can return which cars were used in a given date, or which sessions does a car have in a given date, since I have created a webservice in java that is waiting to get something like:
#GET
#Path("/getData/{car}/{session}")
So the uri I am working with in the webservice (which I tested and works, and I want to connect with what I have in angular2 via tomcat) would be something like:
http://localhost:8080/Project/rest/projectName/getData/55/99
So I believe that is done with routing but 1º I haven't found examples that go deeper than /path (so, not /path/getData/data/data , in this case) , and 2º I am not really getting how to use what can be seen in the official tutorial { path: 'hero/:id', component: HeroDetailComponent }];
It is quite confusing and as of right now I do not feel I have the level to do all those steps (and there are many that I don't need, either), it all seems too complex

Ember Documentation understanding - Model linked to Template or not?

I'm learning Ember right now and i'm beeing a bit confused because of the Docu of Ember and the getting started example.
In the Documentation it says:
In Ember.js, templates get their properties from controllers, which decorate a model.
And
Templates are always connected to controllers, not models.
But after doing the getting started guide i'm not sure if this is correct.
I've uploaded the finished TodoMVC app here: https://github.com/Yannic92/stackOverflowExamples/tree/master/Ember/TodoMVC
In the Index.html you'll find this template:
<script type="text/x-handlebars" data-template-name="todos/index">
<ul id="todo-list">
{{#each todo in model itemController="todo"}}
<li {{bind-attr class="todo.isCompleted:completed todo.isEditing:editing" }}>
{{#if todo.isEditing}}
{{edit-todo class="edit" value=todo.title focus-out="acceptChanges" insert-newline="acceptChanges"}}
{{else}}
{{input type="checkbox" checked=todo.isCompleted class="toggle"}}
<label {{action "editTodo" on="doubleClick"}}>{{todo.title}}</label>
<button {{action "removeTodo"}} class="destroy"></button>
{{/if}}
</li>
{{/each}}
</ul>
</script>
My question refers to the 3rd Line:
{{#each todo in model itemController="todo"}}
The Controller todo is only needed to provide the actions for the todos. The data is accessable even without this controller.
In my opinion there is the model directly connected with the template isn't it?
Or is there a default Controller like the docu mentioned here?
For convenience, Ember.js provides controllers that proxy properties from their models so that you can say {{name}} in your template rather than {{model.name}}.
As you can see in this line: <script type="text/x-handlebars" data-template-name="todos/index"> this is the template for / because the router has this line: this.route('todos', { path: '/'}). Which will have a controller named TodosController, even if you didn't write one ember will generate one for you. So when you delete it that's what happens.
In this template you loop through the todo's list. Each of these Todo models are decorated with a controller the TodoController. And with this line: {{#each todo in model itemController="todo"}} you tell ember to use this TodoController for every element in the list.
If you leave out the itemController ember assumes the todo's are part of the model for the IndexController provided by the IndexRoute.
By default ember has an empty controller which proxies everything to the underlying model. (Note: I believe this will change in ember 2.0). So it may look like it's directly coupled to the model. But you could write a controller that changes everything without changing the model.

Categories

Resources