EmberJS: Nothing handled the action - ember.js

Ember newbie. Using 2.3.0. To an existing application I need to add a button that toggles content on and off the screen. Following the existing code patterns, I added the following two files.
app/components/help.js
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
toggleHelp() {
this.toggleProperty('isShowingHelp');
}
}
});
templates/components/help.hbs
<div class="help">
<a href="#" {{action "toggleHelp"}}>help</a>
</div>
{{#if this.isShowingHelp}}
<p>HELPHELPHELP</p>
{{/if}}
And then in various *.hbs files I'm adding {{partial "components/help"}} to get the button to show up where it is needed.
The button renders as expected as
<div class="help">
help
</div>
But when I click, I get the error, "Nothing handled the action 'toggleHelp'. 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."
I checked the Ember documentation and saw that this matches the instructions.
I think the issue might be because I am calling it as a partial, but none of the other options (view, render, outlet) seems to apply to my limited case.
As per this answer, I tried {{action "toggleHelp" target='component'}}, but then the error when I click turned into, "ember.debug.js:29112 Uncaught TypeError: Cannot read property 'send' of undefined."
I'm at a total loss... Can anyone point out what I'm missing here? Thanks!
Update:
If I copy toggleHelp into the controller going along with one of the .hbs files, then the link works properly. But surely the right way cannot be to put this in multiple controller files? (And when I try to put toggleHelp in controllers/application.js, in hopes that would cover everywhere (?!), I'm back to the original error.)

Your problem is indeed {{partial "components/help"}}!
In general you should not use partials. To call a component you use {{component-name}}.
However components in Ember 2.3 need to have a - in their name. So help is not valid!
rename your component into something like my-help. So app/components/my-help.js for your js and templates/components/my-help.hbs. Then you can just do {{my-help}} to use the component.

Related

How do I replace invokeAction attributes on link-to components in EmberJs?

I have a piece of code like {{#link-to "schedule.feed" invokeAction=(action "toggleNavigation")}}
Which gives me this error message: Do not use action as (action ...). Instead, use the on modifier and fn helper.ember-template-lint(no-action)
How do I replace action here? I tried changing it to an onclick and using fn but that didnt seem to work
Unfortunately, the ember-invoke-action addon for Ember.js has not been updated in some time, and does not work well with the latest Ember Octane code. I would recommend that you template-lint-disable this particular warning for now.
Update: The on modifier with the LinkTo component works well in Ember Octane.
<LinkTo "schedule.feed" {{on "click" this.toggleNavigaion}}>Feed</LinkTo>
See this in action here: https://ember-twiddle.com/c94e0aed7246e86ff81c0fc43b978b1d?openFiles=templates.application%5C.hbs%2C

How to fix warning "interaction added to non-interactive element no-invalid-interactive"

I just upgraded my Ember addon from version 3.0 to version 3.8, and I get this warning now:
Interaction added to non-interactive element no-invalid-interactive
An example of this is something like:
<div class="some-class" onclick={{action "selectDate" "today"}}>
<div> more content </div>
</div>
When you click the action, it should take you to a new route.
What are my options to fix it the right way, so that it is accessible?
The solution here depends on what the action should do.
Refactoring an action that triggers a transition
Since this action takes the user to a new route, it should be a link element, <a> and not a button. This gives assistive technology/screen reader users a clue that interacting will take them somewhere new in the app.
This can be refactored to a link-to in Ember, which will wrap the content in <a>:
{{#link-to someRoute}}
<div> more content </div>
{{/link-to}}
someRoute could be a computed property if it needs to be informed by multiple pieces of data. Otherwise, it could be a string.
Refactoring an interaction that keeps you on the same page
In cases where the action does not take you to a different page, it may be appropriate to use a <button>. An example of this would be a button that expands a collapsible container or toggles a setting. However, the w3 validator tells us that you can't put divs inside of buttons. You can use Phrasing Content that is non-interactive, such as <span>.
<button class="some-class" onclick={{action "toggleSomething"}}>
<span> more content </span>
</button>
Learn More
To catch more accessibility problems in an app, try out ember-a11y-testing which audits your app for problems and gives you a report of how to fix them.
This question was answered as part of "May I Ask a Question" Season 2 Episode 3. If you would like to see us discuss this answer in full you can check out the video here: https://youtu.be/nQsG1zjl8H4

Ember outlet bound to StateManager doesn't render after changing state twice

I've setup a State Manager for tracking user login state, based on this answer here: Change Navbar based on login state
However, I'd like to take it to the next step and have not only the navbar update according to the state, but the main template itself. I've gotten this mostly working so that when you click on the login button it will show you the 'welcome you're now logged in message.' However, if you logout and try to login again, it just shows a blank screen as if it is not correctly re-rendering the index route. Here's a JSFiddle with my issue. Notice what happens when you click on login / logout and then login a 2nd time. the 'welcome' message is not displayed.
Here is my index template:
{{render navbar}}
{{authState}}
{{#if isAuthenticated}}
{{outlet}}
{{else}}
{{render login}}
{{/if}}
I can see the 'authState' is correct, but the 'outlet' is not rendered the 2nd time I login...
Here is the complete jsfiddle:
http://jsfiddle.net/Benmonro/HmJyu/1/
CLARIFICATION
#ham asked for a clarification, so here goes:
The main thing I'm trying to accomplish here is that when a state manager changes the state of isAuthenticated then what is currently rendered in {{outlet}} should be swapped out for what is rendered in {{render login}} which could really be any template. The main point is that {{outlet}} will show and hide w/ the state change...
The reason why it doesn't work is because you have two DOM nodes with id index. In your fiddle is extra </script> at the end of HTML pane but it doesn't matter I guess.
ID in DOM must be unique, otherwise you can see some unexpected issues like this one. You can read more here https://developer.mozilla.org/en/docs/DOM/element.id
Here is working fork of your fiddle - http://jsfiddle.net/wbednarski/eMcXq/
BTW, You may find helpful as well - Difference between == and === in JavaScript
You are not transitioning out of your router, but are only changing the state of your LoginStateManager. If you include the routing output in your App creation, you will see the output, and the lack of transitioning out of your "welcome" state.
Just change App to:
App = Ember.Application.create({ LOG_TRANSITIONS: true });
You will see that using your login-button on the navBar will perform the correct function once, where the button on the login form doesn't transition state, and therefor doesn't show the correct result. This is because in the App.NavBarController you perform this.transitionToRoute("welcome").
Just extend all your logins and logouts with:
this.transitionToRoute("welcome") or this.transitionToRoute("index") and it works like a charm.
[edit] Added an example fiddle here: http://jsfiddle.net/AlphaEagle/rGNca/4/ Hope it helps! [/edit]

How does the buttonClass directive in ember.js work?

This code:
{{bindAttr class="buttonClass:hidden"}}
On this line
That bindAttr code does not appear to do anything. I can remove it entirely and the todo app works just the same as before.
What exactly is the buttonClass directive doing? There is no buttonClass property on the todos controller.
You're right, it is not needed. It was probably there to hide the button if it had no completed tasks. But since it is now wrapped in :
{{#if hasCompleted}}
It should probably be removed.

Updating backed array in Ember.js rc1 does not propogate to view

I am trying to upgrade a partially built UI to the latest Ember.js rc1 and it has turned into a very big rewrite job thanks to the dramatically changed API. Most info out there (and here) has been rendered useless. I've had to go through the documentation again several times to get things partially working but there are a lot of loose ends. Here is a biggie. The views do not update like they did under the previous version. I'm missing something that must have to do with rerender, {{outlet}} or something else that I'm not aware of. The ember guides seem to need updates.
The template is very simple:
<script type="text/x-handlebars" data-template-name="index">
<button {{action "addOne"}}>add one</button>
<ul>
{{#each item in controller}}
<li>{{item.title}}</li>
{{/each}}
</ul>
</script>
When clicked, the button adds a new element to the backed array. The console logs show that the array is growing, but the template does not change. Here is a jsfiddle to illustrate how far I've gotten. Can anyone figure out what needs to be added?
I modified your example to highlight the fact when we use arrays in Ember, that we are using Ember arrays (Ember.A() or Em.A() if you want to make explicit this fact). From my understanding, you can use the methods Em.A().addObject and Em.A().removeObject to achieve the basic functionality using the Ember.Object getter and setter methods, (i.e. .get() & .set()) .
In order be properly observed by the Ember application, it is important to use the Ember getters and setters.
A modified version of your fiddle.