So I have an Ember application that uses bootstrap. I got that working fine it seems, but I'm having issues getting a button from within a dropdown menu to trigger an action. I can have a button outside of that dropdown call the same action, and it works fine.
Controller:
actions: {
clearWords: function(){
console.log("clear it!!");
}
}
HBS:
<li>
<div class="dropdown"> ...
<button type="button" {{action "clearWords"}}>Clear</button>
...
</div>
</li>
<li>
<button type="button" {{action "clearWords"}}>Clear</button>
<!-- ^^ this one works -->
</li>
I've tried adding target to the action bit, but that never works either.
{{action "clearWords" target="controller.controllerName"}}
Any suggestions to get me in the right direction would be much appreciated.
PS: If you happen to be kind enough post sample code from JSBin, could you use JSFiddle instead? I can't see JSBin behind my proxy here :(
Sorry, turns out there was a stopPropagation() called further up in the controller that kept the action from bubbling up. We were using this to keep the dropdown menu open through various clicks.
Hopefully this will help someone else troubleshoot their code. I didn't think bootstrap would be blocking the actions, but this certainly explains it.
Related
I have an odd conundrum.
It appears that when an element is hidden by a focus-out event ember is unable to attach the corresponding click event that triggered the focus out properly. For example with the code below if the <a> tag triggers the focus-out event on the input and the code behind turns _focused to false then the selectOpts event is never triggered. It appears to only happen if the a tag is hidden as a result of the focus-out.
Also oddly it does not matter how the a tag is hidden either if i do just display:none it still also doesn't fire the selectOpt action.
Here is my code:
<div class="dropdown">
{{input value=value class='form-control' focus-in="focused" focus-out="unfocused" }}
{{#if _focused}}
<ul class='dropdown-menu'>
{{#each _filteredOptions as |opt|}}
<li><a href="#" {{action "selectOpt" opt}}>{{opt}}</a></li>
{{/each}}
</ul>
{{/if}}
</div>
Here is a ember twilldle showing the issue.
https://ember-twiddle.com/6bbdb669d19d7a498e645bb0297f1b46?openFiles=templates.components.input-autocomplete.hbs%2Ctemplates.components.input-autocomplete.hbs
In order to get it to show the issue focus in on the text area and then try to select one of the links that appear below the input. What is supposed to happen is that when you select the link it is to populate the input field with the value.
You can use just focus-in instead of both focus-in and focus-out. So when you click on input focus-in event trigger and set _focused to true. Then, in action selectOpt you set value and after that set property _focused to false.
<div class="dropdown">
{{input value=value class='form-control' focus-in='focused' }}
{{#if _focused}}
<ul class='dropdown-menu'>
{{#each options as |opt|}}
<li>
<a href="#" {{action "selectOpt" opt}}>{{opt}}</a>
</li>
{{/each}}
</ul>
{{/if}}
input-autocomplete.js
actions: {
focused() {
this.set('_focused', true);
},
selectOpt(opt) {
console.log(opt);
this.set('value', opt);
this.set('_focused', false);
}
}
I didn't include all code for input-autocomplete it's the same as before exxept actions. Also I used options array insted your filter because didn't get any results when clicked on input.
I have the following bit of template in a project I'm working on:
<div class="item row" {{action "expandItem"}}>
{{input type="checkbox" checked=isChecked}}
{{item.name}}
</div>
The trouble I'm running into is that clicking the checkbox does not change its state. It does, however, fire the expandItem action. I'd like the behavior to be that clicking on the checkbox changes isChecked but clicking anywhere else in the div fires expandItem. How can I accomplish this?
EDIT: The question Stop click propagation from Ember action is very close, but the difference as I see it is that the child element in the other question is using the {{action}} helper, which can easily stop propagation with bubbles=false. In my case, I don't necessarily have a hook into how Ember's default Input Component bubbles the action
SECOND EDIT: I recreated exactly the behavior I'm seeing in this JSBin. You'll notice how the Input Component and the inline action helper behave differently. Hope this helps.
Since Ember 1.13.3 you can do the following (the example does not use input helper and I would not recommend using it if possible):
Template:
<label onclick={{action "stopPropagation"}}>
<input type="checkbox" checked={{checked}}
onchange={{action "check" value="target.checked"}}>
</label>
Component/controller:
actions: {
check() {
this.toggleProperty('checked');
},
stopPropagation(event) {
event.stopPropagation();
}
}
You cannot just stop action from propagating with bubbles=false since in this case event.preventDefault is also called disabling default checkbox behavour.
Here is Ember Twiddle
I was intrigued by this problem, as far as I see there is no native way to prevent bubbling the event from an input helper.
But there is a workaround. Create a non visible div floating above the checkbox, and use a click event that selects the underlying checkbox:
Template:
<div class="item row" {{action "expandItem"}}>
<div style="position-absolute; display: inline-block;">
<div {{action "toggleSelect" bubbles=false}} style="position: absolute;left: 0;width: 12px;top: 0;bottom: 0;"></div>
{{input type="checkbox" checked=isChecked}}
</div>
{{item.name}}
</div>
Action in Controller/Component:
actions: {
toggleSelect() {
this.set('isChecked', !this.get('isChecked'));
}
}
I have a template where I have the following code:
<div {{bind-attr class=":suggestions isRecept::disabled"}} {{action "toggleRecept"}}>
<!-- skipped the rest -->
<a {{bind-attr href="recept_pdf" bubbles=false}}>Click for the recept!</a></p>
</div>
I want to link to an external pdf file. However when a user click on the link, the toggleRecept visibility action is fired. The bubbles=false is incorrect code, but that is what I wanted.
I know it is possible to limit the action, but I am curious if it is possible to do some bubble preventing on a simple HTML attribute.
I have a header with some login/signup forms that popup when you click the respective buttons.
While it was working fine using just jQuery, I've now started to integrate Ember into the application and I'm running into some trouble with some simple toggle functionality.
Here's the basic HTML markup:
<header>
<h1>Page Title<h1>
<nav>
<a id="toggles-login" class="button {{active_class_binding}}">Login</a>
<a id="toggles-signup" class="button {{active_class_binding}}">Signup</a>
</nav>
<div id="popup-forms">
<div id="login-form"></div>
<div id="signup-form"></div>
</div>
<header>
I'm completely new to Ember and I really have no idea how to set this up. The only thing I want is to be able to set the popup forms up as Ember.View objects and toggle them with some action helpers.
I really am lost on this one.
A simple solution would be to trigger simple actions to show the respective forms:
<a id="toggles-login" class="button {{active_class_binding}}" {{action showLoginForm target="view"}}>Login</a>
<a id="toggles-signup" class="button {{active_class_binding}}" {{action showSignupForm target="view"}}>Signup</a>
The corresponding view would have to implement both actions:
App.YourView = Ember.View.extend({
showLoginForm : function(){
this.$("#login-form").toggle();
},
showSignupForm : function(){
this.$("#signup-form").toggle();
}
});
I’ve been trying, using Rails/Ember pre-4, to do a fairly typical thing, that is have a page with a navbar and a content section. The navbar only changes on login (shows logout button when logged in and login and register buttons when logged out), not on every page change.
At first thought i could do something in the application.hbs template such as:
{{view navbar}}
{{outlet}}
where i set up navbar to respond to login state changes (managed by a state manager). This didn’t seem to work.
Then i tried something like (also in application.hbs):
{{outlet navbar}}
{{outlet}}
and tried setting navbar in each route, which results in lots of duplication and also didn’t ultimately work.
Before posting code, wanted to know if anyone already has a good solution to this common situation where certain parts of your page such as a navbar or sidebar only change upon some change in app state, not on every page change.
There are lots of ways to get this done. The first approach you described is closest to what we are doing. In past ember versions we used view helper for this, today we use {{render}} but it's the same basic concept. For example, application.hbs might look like this:
{{render navbar}} {{outlet}}
Now navbar.hbs can use a simple {{#if}} helper to swap links based on login state.
<div class="navbar">
<div class="navbar-inner">
{{#linkTo index class="brand"}}My App{{/linkTo}}
<ul class="nav">
<li>{{#linkTo index}}Home{{/linkTo}}</li>
<li>{{#linkTo about}}About{{/linkTo}}</a></li>
</ul>
<ul class="nav pull-right">
{{#if isAuthenticated}}
<li><a {{action logout}} href="#">Logout</a></li>
{{else}}
<li><a {{action login}} href="#">Login</a></li>
{{/if}}
</ul>
</div>
</div>
Now we add logic to NavbarController that tracks and manages login state.
App.NavbarController = Ember.ArrayController.extend({
isAuthenticated: false,
login: function() {
this.set('isAuthenticated', true);
},
logout: function() {
this.set('isAuthenticated', false);
}
});
In a real app NavbarController would proxy these requests to another controller, perhaps currentUserController. I've created a working sample here: http://jsbin.com/iyijaf/6/edit