How to handle a CSS property of clicked object in Ember? - ember.js

Tell me please, how to handle onclick action by ID. For example, i’ve something in hbs template:
<button id="myButton" {{action "myAction"}} >OK</button>
it has CSS:
button {color: "red";}
How to do two things by onclick action:
1. Set property to clicked object (only to clicked), eg to set CSS colour “green”,
2. Get some property of clicked (eg CSS colour), and console log or alert.
Thanks in advance!

You can connect the action to the "onclick" event of the button like this
<button id="myButton" onclick={{action "myAction"}} >OK</button>
And then the first argument of the action will be the click event, from which you can take the target DOM element.
Check out this example twiddle:
https://ember-twiddle.com/1d14560e0e979dbbdddbfee57c84601c?openFiles=templates.application.hbs%2C

Related

Event handling in EmberJS components using {{#event}} blocks

I've been working on a UI in Ember and I am having difficulty implementing some of the event handling as described on the documentation here
I have a section of a nav bar I need to highlight on hover. The nav bar is made up of ember-bootstrap components.
{{#bs-navbar type="dark" backgroundColor="primary" as |navbar|}}
{{navbar.toggle}}
<div class="container-fluid" style="padding-left:50px;padding-right:50px; ">
<a class="navbar-brand" href="#"><img style="max-width:250px; margin-top: -12px;margin-bottom: -12px" src="/assets/images/logo_white_3x.png"></a>
{{#navbar.content}}
{{#navbar.nav as |nav|}}
{{#nav.item class="highlight-active"}}
{{#nav.link-to "index"}}LIVE{{/nav.link-to}}
{{/nav.item}}
{{/navbar.nav}}
{{/navbar.content}}
<div class="navbar-nav mr-left">
{{#navbar.content}}
{{#navbar.nav as |nav|}}
{{#nav.dropdown class="{{isHover}}" as |dd|}}
{{#dd.toggle }}Link<span class="caret"></span>{{/dd.toggle}}
{{#dd.menu as |ddm|}}
{{#ddm.item}}{{#ddm.link-to "index"}}Link{{/ddm.link-to}}{{/ddm.item}}
{{#ddm.item}}{{#ddm.link-to "cau.all"}}Link{{/ddm.link-to}}{{/ddm.item}}
{{/dd.menu}}
{{/nav.dropdown}}
{{#nav.item}}
{{#nav.link-to "index"}}Current User: <b>MICKEY MOUSE</b>{{/nav.link-to}}
{{/nav.item}}
{{/navbar.nav}}
{{/navbar.content}}
</div>
</div>
{{/bs-navbar}}
To accomplish this I tried to use one of the block events described n the documentation:
//template
{{#hover}}
<h1>link</h1>
{{/hover}}
//component
export default Component.extend({
hover() {
alert('hovered')
},
actions: {
//actions here
}
});
This produces the following error: hover not found, and the catch-all block handler didn't handle it
I thought it might be because the name of the even must be hyphenated so changed it accordingly. This produced a no component or helper by that name error.
Copying and pasting the same text from the guide produces the same errors which suggests there is something more fundamental I am not understanding.
Can anyone shed any light?
First off, if you need to highlight a navbar on hover, you should be doing this with css.
.someClass:hover: {
//apply highlight style
}
As for what's wrong with what you're doing in general, go back and look at those linked docs again. There's no event that ember handles called hover. What you're looking for is mouseEnter and mouseLeave. Check this twiddle to see an example:
export default Component.extend({
mouseEnter(){
this.set('hovering', true);
},
mouseLeave(){
this.set('hovering', false);
}
});
Where we only show the passed block on hover
Hover here ->
{{#if hovering}}
{{yield}}
{{/if}}
Try use an action for the mouseEnter event, e.g. <div mouseEnter={{action "showCaution"}}>
Another way to preserve native event behaviors and use an action, is
to assign a (closure) action to an inline event handler.
The action is simply a function defined on the actions hash of a component. Since the action is assigned to an inline handler, the function definition can define the event object as its first parameter.
actions: {
showCaution(event){
// Only when assigning the action to an inline handler, the event object
// is passed to the action as the first parameter.
}
}

How to expand/collapse on partial title when using the semantic-ui-react accordion

I have an accordion title that consists of the carat, some text, and a div with some other stuff. I want the accordion to only expand when the user clicks the carat or the text, but not the extra div. Clicking on the div will do something else entirely.
I noticed that in the base Semantic-UI, you can specify a CSS selector to trigger on, but that seems JQuery specific and not doable in the react version.
Is this possible?
<Accordion.Title
active={activeIndex === 0} index={0} onClick={this.handleClick}
>
<Icon name="dropdown" />
<span className="name">{data.name}</span>
<div>some extra junk - don't expand on this</div>
</Accordion.Title>
Your onClick event is attached to the Accordion.Title itself. That means when you click that component, your handleClick function will fire. If you want the handleClick function to fire when clicking the Icon then you need to move your handler function to that component instead.
<Icon
name='dropdown'
onClick={this.handleClick}
/>

How to stop the inner action from bubbling to the outer link-to helper?

When clicking the "edit" to trigger the action "edit":
{{#link-to "pages.show" page class="list-group-item"}}
{{page.name}}
<span class="badge" {{action "edit" page preventDefault=false}}>edit</span>
{{/link-to}}
Then the action is triggered (e.g. the edit page is opened), but in the next second the link-to redirect is done so I end up on the "pages.show" route.
Expected: Solely the action "edit" is invoked and the click event(?) is not "bubbled" to the link-to helper.
Side notes Ember 2.2 is used and the template above is part of a component.
PS: I red that using preventDefault=false inside an action would stop this type of behavior - but obviously the link-to helper gets the information from somewhere else.
What you need is called event bubbling. You can disable it by using bubbles=false inside your action helper, so your click event won't bubble up to the link-to element
{{#link-to "pages.show" page class="list-group-item"}}
{{page.name}}
<span class="badge" {{action "edit" page bubbles=false}}>edit</span>
{{/link-to}}
http://emberjs.com/api/classes/Ember.Templates.helpers.html#toc_event-propagation
preventDefault is a different thing, when setting preventDefault to false, you allow the default browser action of the DOM event.

Integrating ember-modal-dialog inside a site header Ember 2.0

I'm very new to the Ember framework and I have a question regarding getting a modal setup. I have the site-header as a component. When I click a login button I'd like for a modal to popup. I found the Ember Modal Dialog
plugin and was able to set it up so that there is a modal always shown in application.hbs. However, I'm having trouble understanding a couple of things but first here are my files.
application.hbs
{{site-header}}
{{outlet}}
{{#if isShowingModal}}
{{#modal-dialog close="toggleModal"
alignment="center"
translucentOverlay=true}}
Oh hai there!
{{/modal-dialog}}
{{/if}}
{{site-footer}}
site-header.js
import Ember from 'ember';
export default Ember.Component.extend({
isShowingModal: false,
actions: {
toggleModal: function() {
this.toggleProperty('isShowingModal');
}
}
});
So, I have this code for the button in my site-header.hbs:
<li class="login-button"><button class="btn btn-block btn-danger" {{action 'toggleModal'}}>Login</button></li>
As I understand it, action is saying to find toggleModal property in the site-header.js and execute the function above which does the property toggling.
However, how does application.hbs "see" the value of isShowingModal? Can it even see that value since the modal isn't showing up?
When most developers have modals, do they all go inside application.hbs since you want them to appear in the middle of the screen {{outlet}} area? How can you improve the process for including multiple modals?
What changes should I make to make the modal show up when the user clicks a button in the header?
Ok give this a try. In site-header.js
export default Ember.Component.extend({
actions: {
toggleModal() {
this.sendAction('toggleModal');
}
}
});
Application.hbs
{{site-header toggleModal='toggleModal'}}
{{outlet}}
{{#if isShowingModal}}
{{#modal-dialog close="toggleModal"
alignment="center"
translucentOverlay=true}}
Oh hai there!
{{/modal-dialog}}
{{/if}}
{{site-footer}}
The application controller
export default Ember.Controller.extend({
actions: {
toggleModal() {
this.toggleProperty('isShowingModal')
}
}
})
So the action is sent from the site-header component to the site-header component. From there it gets sent to the application controller. In application.hbs, toggleProperty='toggleProperty' connects the action from the component to the controller's action hash. In the controller action hash, it gets handled by toggleModal() and toggles the isShowingModal property. When the modal is closed, ember-modal-dialog fires an close action that is handled by the toggleModal() which again toggles the isShowingModal property.
Application template cannot see the properties of site-header. Only site-header component can see its properties. There are other methods to access them.
It is not necessary to include all modals in application. The plugin will most probably handle the positioning. In your case, you can move the modal code to the site-header component also.
Put the modal code in your site-header template. (or) You can have isShowingModal variable in application, send an action from site-header to application and toggle its value.

Execute action on link-to

I want to add an action to a {{link-to}} helper.
For example, in a modal component, I use {{link-to}} to open a new route. When the user clicks the link, I want to close the modal through an action.
One possible solution is to wrap an action around a {{link-to}}:
<button {{action "close"}}>
{{#link-to 'register'}}Registreer{{/link-to}}
</button>
Is this the best / cleanest solution possible? Or can I add an action to a link-to helper?
Another approach might be to transition and close in a custom action, but this approach is not
usable for use in a component:
// template.hbs
<button {{action "link" "register"}}>Registreer</button>
...
// template-controller.js
actions: {
link: function(routeName) {
this.transitionToRoute(routeName);
this.close()
}
}
You should do teardown operations such as closing modal boxes within the willDestroyElement event of your current view.
By doing this, you could just {{link-to 'register'}} and let your view (template-view.js) manage the fact that there is a modal to close or not.
Checkout the docs of willDestroyElement HERE