Ember.js modal component - where should I write the openModal action? - ember.js

I am trying to setup a modal window as outlined in this post:
http://blog.atmartin.io/a-dead-simple-ember-cli-modal/
The author indicated that the openModal action is written in the app/controllers/application.js...
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
openModal: function(targetId) {
var modal = Ember.Views.views[targetId];
modal.send('toggleModal');
}
}
});
However, I am using the component from the books list page, using a test button:
<button {{action 'openModal' 'modal-author'}}>Open Author Modal Window</button>
{{#simple-modal enabled=false title="--Simple Modal --" id="modal-author"}}
Modal text. Oh girl!
{{/simple-modal}}
So, I tried (I may be wrong...) to insert the openModal action (when the button is clicked) into the book.js route:
// app/routes/books.js
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.store.findAll('book');
},
actions: {
openModal: function(targetId) {
var modal = Ember.View.views[targetId];
modal.send('toggleModal');
},
....
}
});
In this case, I get an error Ember.view seems to be undefined ...
books.js:11 Uncaught TypeError: Cannot read property 'views' of undefined

You are using a tutorial that utilizes a deprecated & removed construct (views) in recent versions of Ember.
I recommend you use the https://github.com/yapplabs/ember-modal-dialog addon for creating modals in recent versions of Ember.

Related

sendAction is not working for component in ember js

sendAction is not working for component. When using component inside view and sending action from component to view.
confirm-dailog.js
import Ember from 'ember';
export default Ember.Component.extend({
actions:{
closeConfirmDialog:function(){
this.sendAction('onCancel');
}
}
})
confirm-dailog.hbs
<div class="dialog" id="dialog">
<div class="text">{{text}}</div>
<div class="button"{{action 'closeConfirmDialog'}}>Cancel</div>
</div>
modal.js
import Ember from 'ember';
export default Ember.View.extend({
layoutName: 'components/modal-box',
actions:
{
closeDialog:function()
{
console.log('called model closedialog')
},
}
})
modal-box.hbs
<div class="dialog" id="dialog">
{{yield}}
{{confirm-dialog onCancel="closeDialog" text="Would you like to close the modal"}}
</div>
when i am clicking on cancel button closeConfirmDialog action gets called and from there i am trying to send closeDialog action but its showing error Nothing handled the action 'closeDialog'
here i have added screenshot of ui
Ember : 1.8.1
Ember Data : 1.13.7
Handlebars : 1.3.0
jQuery : 1.11.1
Views are removed from Ember 2.0 API. http://emberjs.com/deprecations/v1.x/#toc_ember-view
I would encourage you to replace view with Component.
Moreover for your requirement ember-elsewhere addon or ember-modal-dialog would be most suitable.

Use an application's route's action in a template component

Firstly, I'm fairly new to Ember, so the way things interact muddles me up easily.
I am working within an existing Ember application. In the app's routes/application.js.es6 there are actions defined. Given that these actions are in the application route, can I access them from anywhere?
I am specifically looking to use one of the application's route's actions in a template/component.
In the component's js file, do I need to inject or import something to use the action from the application route?
This demo perfectly demonstrates the thing you try to achieve.
First, define action in application route:
import Ember from 'ember';
export default Ember.Route.extend({
actions: {
myActionFromApp() {
console.log('myAction from application fired');
}
}
});
Then in template pass name of action to component:
{{my-component myAction='myActionFromApp'}}
Then you can call your ApplicationRoute action from component:
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
myAction() {
this.sendAction('myAction');
}
}
});
In demo I do it when someone clicks button:
<button {{action 'myAction'}}>Fire action myAction</button>
Result in console is:
myAction from application fired
When you click on button which is expected.

How to communicate nested component to mixin without using service

I have a nested component. The child-component has an input field bind with mixin variable and action, In parent-component had button action. ( without mixin because parent-component considered as a addon ) while button action triggers the child-component value update to the mixin variable. How trigger a child action from parent-component.
Note: Please refer the attached demo link
https://ember-twiddle.com/d8b01ba563b555fc01374f300db20c5b?openFiles=components.child-component.js%2C
An easier approach than triggering actions on your child-component would be to pass the updated_val down to the child component, and let the ember value-binding do the rest. When the value has changed and you click update, make your ajax call from your dialog-component.
e.g. for passing your updated_val down
//application.hbs
{{dialog-component updated_val=updated_val}}
But since your question was "How to trigger actions on a child component", this might be an approach (see updated twiddle):
//dialog-component.js
import Ember from 'ember';
export default Ember.Component.extend( {
actionCalled: false,
actions:{
callChildAction() {
this.toggleProperty( 'actionCalled' );
},
updateValue(updateVal) {
this.set('updated_val', updateVal);
}
}
});
//dialog-component.hbs
<div class='dialog'>
{{!pass your 'updateValue' action from the dialog-component to the child-component}}
{{ child-component actionCalled=actionCalled updateValue=(action 'updateValue')}}
<button {{action 'callChildAction' }}> Update </button>
</div>
//child-component.js
import Ember from 'ember';
export default Ember.Component.extend( {
child_val: '',
actionObserver: Ember.observer('actionCalled', function(){
this.send('childAction')
}),
actions:{
childAction(){
alert( 'childAction called..' );
// some validation and ajax call.
this.sendAction('updateValue', this.get('child_val'));
},
}
});
//child-component.hbs
{{input value=child_val}}

change controller property from another controller

I have an application that has a Navigation bar that I have put in "Application" context. By default, these Navigation bar links will be disabled and will be enabled only on a particular action from template.
The Application controller that contains the disabled status of the link in Nav Bar:-
App.ApplicationController = Ember.Controller.extend({
userName:"TestUser",
firstLinkDisabled:true,
actions:{
handleToggle:function(){
console.log("Handling application action with linkstatus="+this.firstLinkDisabled);
//this.set("firstLinkDisabled",false);
this.toggleProperty("firstLinkDisabled");
}
}
})
The Index Controller that will send the action to Application Controller:-
App.IndexController = Ember.Controller.extend({
actions:{
toggleApplicationButton:function(){
this.controllerFor("Application").send("handleToggle");
}
}
})
Application Template:
<script type="text/x-handlebars">
{{#link-to 'first' disabled=firstLinkDisabled}}First link in application{{/link-to}}
<button {{action 'handleToggle'}}>Toggle Application Menu </button>
{{outlet}}
</script>
Index Template
<script type="text/x-handlebars" id="index">
<button {{action 'toggleApplicationButton'}}>Toggle Application Menu </button>
</script>
When I click on "Toggle Application Menu" button I get the following output in console.
Console Output
But in Ember inspector the property "firstLinkDisabled" doesn't change. Image of Ember Inspector:-
Ember Inspector Image
The link remains disabled.
What am I doing wrong here?
Doesn't ember allow to change the property of other controller?
How to make this thing work?
Here is a simple example from my project:
import Ember from 'ember';
export default Ember.Controller.extend({
/*first, inject a controller*/
loginController: Ember.inject.controller('lang.login'),
/*some code*/
actions: {
register: function () {
/*some code*/
/*work with injected controller*/
var c = this.get('loginController');
c.set('identification', that.get('user').email);
c.set('password', that.get('user').plainPassword);
/*some code*/
}
}
});
ember docs
Use Ember.inject.controller()
App.IndexController = Ember.Controller.extend({
appController: Ember.inject.controller("Application"),
actions:{
toggleApplicationButton:function(){
this.get("appController").send('handleToggle');
}
}
})
controllerFor you can use in the Routes
Also you can use the alias
appController: Ember.computed.alias('controllers.Application')
Refer Emberjs official documentation for detail
First, inject the application controller into the index controller
//index.js
application: Ember.inject.controller(),
Then you can access the property in the application controller like this:
//index.js
application.toggleProperty("firstLinkDisabled");

Access jquery event from ember component action

I'm trying to work with a simple overlay component, and close this overlay if someone clicks outside of the overlay content:
<div class="overlay" {{action 'close' on='click'}}>
<div class="item">
<form {{action 'submit' on='submit'}}>
{{yield}}
{{#link-to closeRoute class="close"}}Close{{/link-to}}
</form>
</div>
</div>
The component looks like this:
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
submit: function() {
this.sendAction();
},
close: function(param) {
console.log(param); // -> undefined
console.log(this); // -> complete component object, no reference to the event?
// this.$("a.close").click();
}
}
});
This works like advertised, however, I need to determine the target of the click event, because also clicks on the item and form will trigger this click(close) action.
Question: How can I access the (jQuery) event object which has a target from within the close action inside the component?
I am using EmberCLI, and Ember 1.9
I have found this to provide the required result:
export default Ember.Component.extend({
classNames: ['overlay-block'],
didInsertElement: function() {
var self = this;
self.$().click(function(e) {
if (self.$(e.target).hasClass("overlay-block")) {
self.$("a.close").click();
}
});
}
});
This does not use an ember action like I expected. I'll leave the question open for a while to see if somebody comes up with an more 'Ember way' of doing this.
More Ember way
export default Ember.Component.extend({
classNames: ['overlay-block'],
click: function(e) {
if (this.$(e.target).hasClass("overlay-block")){
this.$("a.close").click();
}
}
});