How does the buttonClass directive in ember.js work? - ember.js

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.

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

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.

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.

Can a Ember.Component have both a block and non-block form?

I would like to build an Ember.Component that can be used either in block form, or without a block when some default behavior is desired.
For example, in block form:
{{#my-helper}}
...
{{/my-helper}}
Or non-block form:
{{my-helper}}
Where the helper template is somehow able to detect that there is not a block and behave accordingly. For example, it would be nice if there was some way to detect the block:
{{#if hasBlock}}
{{yield}}
{{else}}
default output
{{/if}}
For my requirements, I need to have some way to output something only if there's not a block.
Any ideas how to do this?
update:
If you're confused by why my question is the same as the accepted answer it's because Ember happened to adopt new syntax that is exactly what I originally imagined up as desirable. When I first asked this question it turned out there was an undocumented way to do this using {{#if template}} but that has since been deprecated with Ember 2.x and there's new syntax {{#if hasBlock}} which happens to match how I phrased my question.
Inside the Component you'd want to check the value of hasBlock
{{#if hasBlock}}
{{yield}}
{{else}}
<p>Default content for inline (non-block) form of the component.</p>
{{/if}}
Here's a JSBin : http://jsbin.com/IWEKere/1/edit
The link to the docs is here: http://emberjs.com/api/classes/Ember.Component.html#property_template
The docs don't explicitly say that the template attribute is used in this way. Since the Ember.Component class inherits from the Ember.View class, it can be inferred that the component template acts like the Ember.View layout template.
"template" has been deprecated in favour of partial, eg.
{{#if partial}}
{{yield}}
{{else}}
<p>Default content for inline (non-block) form of the component.</p>
{{/if}}
Accessing template directly is currently deprecated, but there is a feature-flagged hasBlock property (which basically does !!template under the hood) that should be used in this case.
The feature flag is ember-views-component-block-info
Here's a link to the merged pull request: https://github.com/emberjs/ember.js/pull/10461

What changed on the {{action}} behavior since RC3.1 that breaks the ember.js todo code

Im currently working through the Ember.js Getting started Guide, but i'm using v1.0.0-rc.6.3 instead of RC3.1 as mentioned in the Guide.
Now i reached the chapter about implementing the editing of single todos, but the {{action}} handler implemented in the Guide dosn't seem to work, so my fist assumption is that the behavior of events changed.
Here is my code so far in a JSBin: http://jsbin.com/ogixej/1/edit
As you can see, when you double click a todo item a error is raised in the console:
Uncaught Error: Nothing handled the event 'editTodo'.
Could you tell me what changed an how i'm supposed to do it in a correct manner?
Since your TodoController is the controller responsible for the items you need to define this on your TodosController, like this:
Todos.TodosController = Ember.ArrayController.extend({
itemController: 'todo',
...
});
This way the editTodo function is correctly invoked. Here your working jsbin.
Hope it helps.
I recognize that this should be a comment, but my reputation is too low, yet.
While #intuitivePixel's answer is correct, and accepted, it did not work for me later in the example, during the Transitioning examples (Getting Started Guide - Adding Child Routes). Once I broke the templates apart, I had to move the itemController property from the controller and into the template, during the {{#each}}, like so:
{{#each itemController="todo"}}
...
{{/each}}
If you look closely, you can find this code in Ember's first example block, but it's not called out in the surrounding narrative, so I missed it.