ember modal dialog wont close - ember.js

I have used ember-modal-dialog. I have set the modal to close (as per the example on git - https://github.com/yapplabs/ember-modal-dialog). But it does not close when I click the background.
application.hbs
{{#if isShowingModal}}
{{#modal-dialog close="toggleModal" targetAttachment="center" translucentOverlay=true}}
abc
{{/modal-dialog}}
{{/if}}
applications.js
export default Ember.Controller.extend({
isShowingModal: false,
actions: {
showNavMenu: function() {
this.toggleProperty('isShowingModal');
}
}
});

you are triggering "toggleModal" function on clicking close button of model. as your code you define showNavMenu function to toggle the property isShowingModal
your code should be close = "showNavMenu" so on click close button this function called and model close properly.
correct code is
{{#if isShowingModal}}
{{#modal-dialog close="showNavMenu" targetAttachment="center" translucentOverlay=true}}
abc
{{/modal-dialog}}
{{/if}}
or change the function name in controller from showNavMenu to toggleModal

Related

How to test that an action is fired in a component integration test?

I have a very simple component and I'm trying to test that, when the button is clicked, the appropriate action is triggered. I've followed the docs as closely as I can, and also read several blog posts and SO questions covering the same material, and hence tried several subtly different ways of getting this to work but I just cannot get the test to pass. I've confirmed that it does actually work in the browser. What am I doing wrong?
add-thing.hbs:
{{#if displayForm}}
<form class="form-inline">...form content...</form>
{{else}}
<button {{action 'toggleForm'}} class="btn btn-default add">Add</button>
{{/if}}
add-thing.js:
import Ember from 'ember'
export default Ember.Component.extend({
displayForm: false,
actions: {
toggleForm () {
this.toggleProperty('displayForm')
}
}
})
add-thing-test.js:
import Ember from 'ember'
import { moduleForComponent, test } from 'ember-qunit'
import hbs from 'htmlbars-inline-precompile'
moduleForComponent('add-group', 'Integration | Component | add thing', {
integration: true
})
test('it toggles the form when the Add button is clicked', function (assert) {
assert.expect(1)
this.set('assertCalled', () => { assert.ok(true) })
// Have also tried this.on here instead of this.set
this.render(hbs`{{add-thing toggleForm=(action assertCalled)}}`)
// Have also tried passing in the action like {{add-thing toggleForm='assertCalled'}} as some blog posts suggest
Ember.run(() => document.querySelector('button.add').click())
// Have also tried just a this.$('button.add').click() here
})
Test output:
not ok 16 PhantomJS 2.1 - Integration | Component | add thing: it toggles the form when the Add button is clicked
---
actual: >
null
expected: >
null
stack: >
http://localhost:7357/assets/tests.js:221:24
exports#http://localhost:7357/assets/vendor.js:111:37
requireModule#http://localhost:7357/assets/vendor.js:32:25
require#http://localhost:7357/assets/test-support.js:20229:14
loadModules#http://localhost:7357/assets/test-support.js:20221:21
load#http://localhost:7357/assets/test-support.js:20251:33
http://localhost:7357/assets/test-support.js:7708:22
message: >
Expected 1 assertions, but 0 were run
Log: |
...
Ember: v2.14.0
It looks like you have two different things happening.
this.toggleProperty('displayForm')
that action will toggle displayForm from true to false, but it doesn't "bubble up" or go up anywhere. Clicking the button will fire it and then that is it.
Your test, on the other hand, is looking to see if clicking the button fires an action up to another level.
You can test this by checking if the form exists after clicking the button assert.equal(this.$('form').length, 1);. Or you could change the way the component works, but unless you want the action to bubble up you don't need to go that route.
Which might look something like
toggleForm () {
this.sendAction('toggleForm');
}
or
<button {{action toggleForm}}">Add</button>
(note the no quotes on `toggle form this time, that means call the action that was passed in.)

Set focus on a text box in ember js

I am trying to change a text to a text box. If a user clicks the text, it will change to a test box and so they can edit the content. I have done that. I am able to set the focus by below code.
{{input value=animal.name autofocus=true}}
It only works for the first time. If I focus-out, the text box will again change to text content. If I click the text again, I am able to see the text box, but it is not in focus. Below is the code I am trying.
Component file:
import Ember from 'ember';
export default Ember.Component.extend({
isTextBox: false,
actions: {
editTest() {
this.set('isTextBox', true);
}
},
focusOut() {
this.set('isTextBox', false);
},
});
Template file:
{{yield}}
<center><h2>
<div onclick = {{action 'editTest'}}>
{{#if isTextBox}}
{{input value=animal.name autofocus=true}}
{{else}}
{{animal.name}}
{{/if}}
</div>
</h2></center>
I am new to ember and I trying to do the focus without using jQuery.
Here is the twiddle https://ember-twiddle.com/d832c6540ba94901a6c42d5bb3cfa65e?openFiles=templates.components.text-input.hbs%2Ctemplates.components.text-input.hbs.
You can do this in Plain Old Javascript as follows:
didRender(){
// This works but is not very ember-ish
// document.getElementById('cat-text').focus();
// For a component, you can do this
this.get('element').querySelector("#cat-text").focus();
}
This assumes you have an input like this:
{{input id='cat-text' value=animal.name }}
Ember 2.13+ is no longer dependent on jQuery (although some of the add-ons that you use may be), so you have the possibility of eliminating 35kb (min + gzip) that jQuery would add to the payload of your app.
To expand on kumkanillam's answer you can just set the focus at the end of the render lifecycle if it's rendering a textbox. Since you've only got one text input in your component you can just find it with a selector. No need to worry about using jQuery here that's what it's there for so it is the Ember way.
didRender(){
if(this.get('isTextBox')){
this.$('input[type=text]:first').focus();
}
}
You can provide id to input helper,
{{input id='cat-text' value=animal.name }}
You can make it focus text field for every rendering,
didRender(){
this.$('#cat-text').focus();
}
components/input-text-focused/component.js:
import TextField from '#ember/component/text-field';
export default TextField.extend({
didInsertElement(...args) {
this._super(...args);
const element = this.get('element');
if (element) element.focus();
},
});
{{input-text-focused type="text" name="search" value=search}}

Prevent click into {{input}} component from propagating/bubbling up (ember)

I have an {{input}} inside of an element that itself has an action.
How do I prevent clicking into the input from triggering the click event on the parent element?
I have tried bubbles=false.
I have also tried extending {{input}} and in the extended input I caught the click event and called event.preventDefault()
Please try my test case: https://ember-twiddle.com/a2cee9abd63a7400124e2745a7820cf8?numColumns=2&openFiles=controllers.application.js%2Ctemplates.application.hbs
Example hbs:
<div {{action "alert"}}>
I don't want the click into the input to trigger the div's onlick. Help!<br/>
{{input bubbles=false}}
</div>
Define component say my-input which extends Ember.TextField and define click function and return false to prevent bubbling.
import Ember from 'ember';
export default Ember.TextField.extend({
click(){
console.log('click my input');
return false;
}
});
For my-input component, you dont need to define anything to handle click event while including the component. you can just say {{my-input }}
Here is the working twiddle

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.

How to send a click even to a view (it already works but I think it is not the Ember way)

I want to style a button for file upload. I already have a working, but it feels like I dont do it the Ember way.
My view:
App.FileUploadView = Ember.TextField.extend({
(....)
});
template:
{{view App.FileUploadView name="big-image" file=big-image id="big-image"}}
<a {{action clickUploadView}} href="#">Upload file</a>
controller action:
clickUploadView: function(){
Ember.$('#big-image').click();
},
I have fiddled around to use the viewName property like this in my template and call it from the controller: {{view App.FileUpload ... viewName="big-image"}} but could not get the click fired.
Any thoughts or is this just correct?
Wrap your anchor tag in the view helper and add the action to the view, then target the view.
{{#view App.SomethingView}}
<a {{action daClick target="view"}} href="#">Upload file</a>
{{/view}}
App.SomethingView = Em.View.extend({
actions:{
daClick: function(){
alert('hello');
}
}
});
http://emberjs.jsbin.com/eHAsexI/1/edit
Or if you just want it to hit the click event of the view, you can just rip out the action all together and leave the anchor tag in the view and it will hit the click event of the view.
http://emberjs.jsbin.com/eHAsexI/2/edit