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

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

Related

EmberJS: Nothing handled the action

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.

Which is better between Ember statement vs HTML statement in Ember?

I'm new in Ember.
As I know, the Ember is consist of [.js/.hbs(handlebars)].
when I search the component in the google, I got 2 kinds of source.
1st is like 'HTML'
<input type="checkbox" class="btn btn-success active" />CheckBox01<br />
and 2nd is like more 'Ember'.
{{input type="checkbox" checked=true}}CheckBox02
but I think these are same.. so I don't select what I use.
Frankly I want to follow 2nd style, but when I try it('https://www.npmjs.com/package/ember-cli-toggle'), I got failed.
so I just use 1st style these days. and It is more easy to me because I used to handle HTML.
Anyway, the question is what are the different between Ember Style and HTML Style.
Thanks.
Value binding is the main difference. You can as well do dynamic value binding and since they are handlebars, you get the sophistication of many more helpers.
Please read Ember documentation here, if you have not so.
https://guides.emberjs.com/v2.10.0/templates/input-helpers/
Thanks

Ember.js Component Moving DOM elements

I have an Ember.js component called table-viewer. It has a toolbar which is a div with buttons. I have another ember component called report-viewer. It contains a variety of things including a table-viewer.
I want to have report-viewer add some buttons to the toolbar. What I have works but breaks the Ember connection with the element so I can't change the button text after moving it. Is there a better way to do this?
I have a lot more components than I just said, so defining the complete toolbar in table-viewer and setting flags for what to show would be annoying to manage.
Below is what I currently have in table-viewer so that any component can add additional buttons to the toolbar:
Ember.$('#toolbar').append(Ember.$('#additionalToolbar').html());
Ember.$('#additionalToolbar').remove();
I figured it out! The following works without breaking Ember connections:
Ember.$('#additionalToolbar > button').appendTo(Ember.$('#toolbar'));
It's hard to say what the best approach is without seeing the relevant code. That said, my first suggestion would be a simple yield:
report-viewer/template.hbs
{{#table-viewer}}
<button>
Some button from the report viewer...
</button>
{{/table-viewer}}
table-viewer/template.hbs
<nav>
<button>
Button one
</button>
<button>
Button two
</button>
{{yield}}
</nav>
<table>
...
</table>
If you need more that one yield, you can achieve multiple named yields with this approach.
I'd also suggest splitting the toolbar out into its own component if you haven't already. It feels wrong to put a toolbar button as the block contents of the table-viewer component as I've done above.

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]

View management with Ember.StateManager (and not Ember.Router)

I'd like to user Ember to create an 'informational sign' type of application; The data displayed will be updated on a regular basis, but there is no user input or interaction. The application is configured and initialized based on URL parameters provided by an administrator. The layout and content of the application will change depending on the data in the feed the application is monitoring.
Ember.Router seems like overkill for this task because I don't need/can't have URL-based routes mapped to application state. Ember.StateManager seems perfect because it allows me to programmatically transition between states depending only on conditions met within the logic of my application, ignoring the current URL. The deprecated Ember.ViewState seems like it was the way to manage views when using Ember.StateManger.
What is the current best practice for managing views in the DOM with Ember.StateManger?
Is there a way to do what I'm describing with Ember.Router instead?
Thanks,
Aaron
After reading your primary explanation, I feel that you dont need any states at the moment. You need diferent application stated defined when application needs different behaviour in those states. Looks like your application behaviour is not changing but just view.
So you can just use some handlebars condition helpers to make this work along with some derived attribute in your controller indicating whether there is any current advisory.
{{#view App.myView}}
{{#if hasAdvisory}}
<div class="col-2">
<div class="col1">
{{#each bus}}
//bus details
{{/each}}
</div>
<div class="col2">
//advisory details
</div>
</div>
{{else}}
<div class="col-1">
<div class="col">
{{#each bus}}
//bus details
{{/each}}
</div>
</div>
{{/if}}
{{/view}}
Please explain more like if you just need this or do you plan any different application behaviours when you have advisory and when you dont have.
In general, the same techniques used to manage views and controllers in Ember.Router-based apps can be used with Ember.StateManager. Specifically, using outlets with Em.Controller#connectController is an excellent way to switch views that is independent of state management.