Submitting form from a modal in Ember - ember.js

I am trying to make a registration page in ember which is opened when someone clicks the registration button. The registration page is opened in a modal. I used the modal implementation given on Ember websit
http://emberjs.com/guides/cookbook/user_interface_and_interaction/using_modal_dialogs/
Now the registration form opens on clicking the button but I am not able to catch the submit event of the registration form anywhere. You can refer to the code here:
http://jsfiddle.net/jywPL/1/
<script type="text/x-handlebars">
{{outlet}}
{{outlet modal}}
</script>
<script type="text/x-handlebars" data-template-name="index">
<h4>Register</h5>
{{outlet}}
<button {{action 'openModal' 'modal' model}}>Register</button>
</script>
<script type="text/x-handlebars" data-template-name="modal">
{{#modal-dialog action="close"}}
<form class="form-horizontal" {{action "register" on="submit"}}>
<br/>
<div align="center" >
<table class="table-hover">
<tr>
<td>
<label>First Name</label>
</td>
<td>
{{input value=firstName class="controls" type="text"}}
</td>
</tr>
<tr>
<td>
<label>Last Name</label>
</td>
<td>
{{input value=lastName class="controls" type="text"}}
</td>
</tr>
<tr>
<td>
<label>Email</label>
</td>
<td>
{{input value=email class="controls" type="text"}}
</td>
</tr>
<tr>
<td>
<label>Company</label>
</td>
<td>
{{input value=company class="controls" type="text"}}
</td>
</tr>
<tr>
<td>
<label>Company Contact</label>
</td>
<td>
{{input value=contact class="controls" type="text"}}
</td>
</tr>
<tr>
<td>
<label>Reason for request</label>
</td>
<td>
{{view Ember.TextArea valueBinding="reason" rows="10" cols="20"}}
</td>
</tr>
</table>
<br/>
<button type="submit">Register</button>
<button {{action "close"}}>Done</button>
</div>
</form>
{{/modal-dialog}}
</script>
<script type="text/x-handlebars" id="components/modal-dialog">
<div class="overlay" {{action "close"}}>
<div class="modal" {{action bubbles=false}}>
{{yield}}
</div>
</div>
</script>
var App = Ember.Application.create();
App.ApplicationRoute = Ember.Route.extend({
actions: {
openModal: function(modalName, model) {
this.controllerFor(modalName).set('model', model);
return this.render(modalName, {
into: 'application',
outlet: 'modal'
});
},
closeModal: function() {
return this.disconnectOutlet({
outlet: 'modal',
parentView: 'application'
});
},
register: function() {
alert('hello');
}
}
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return Em.Object.create({firstName: '',lastName: '',email:'',company:'',contact:'',reason:''});
},
action: {
register: function(){
alert('Registering');
}
}
});
App.ModalController = Ember.ObjectController.extend({
actions: {
close: function() {
return this.send('closeModal');
},
register: function(){
alert('hello1');
}
}
});
App.ModalDialogComponent = Ember.Component.extend({
actions: {
close: function() {
return this.sendAction();
},
register: function(){
alert('hello2');
}
}
});
.I have tried to trigger action helper called register on form submit but the register action is not triggered. From the modal implementation I see that the action bubbling has been disabled so the action wouldn't be triggered in any of the parent routes. But why is it not triggering in ModalDialogComponent actions tag.

In your ModalController Route, add
action: {
doRegister: function() {
this.register(); //or whatever
}
Then on the submit button
<button type="submit" {{action "doRegister"}}>Register</button>
If your ModalController Route is binding correctly, this should work.

Related

delete multiple records on EmberJS using {{input type="checkbox"}}

I would like to have an action that prints all the selected check-boxes on my table to the console.
in my controller I have
removedSelected: function() {
let selected = this.filterBy('isSelected', true);
console.log(selected);
}
in my template file I have
{{input type="checkbox" checked="isSelected"}}
I have setup my controller to filter all the records that are "isSelected" in the table by using input helper on ember.
I am getting an error on the console which states this.filterBy is not a function
Do i need to setup an array to handle this first?
Below is more of the code for a better picture.
Thanks!
// templates/warranty/index.hbs
<div class="container">
<h4>List</h4>
<div class="row">
<div class="col-sm-3">
<div class="control-group">
{{#link-to 'warranty.new' class="btn btn-primary btn-sm"}}New Claim{{/link-to}}
<button class="btn btn-primary btn-sm" {{action "toggleMultiple"}}>Select</button>
{{#if canDeleteMultiple}}<button class="btn btn-danger btn-sm"{{action "removedSelected" warranty}}>Delete Selected</button>{{/if}}
</div>
</div>
<div class="container">
<table class="table table-striped table-hover ">
<thead>
<tr>
{{#if canDeleteMultiple}}<th>Select</th>{{/if}}
<th>Action</th>
<th>Claim ID</th>
<th>Claim Status</th>
<th>Serial Number</th>
<th>Issue Description</th>
</tr>
</thead>
<tbody>
{{#each model as |warranty|}}
<tr>
{{#if canDeleteMultiple}}{{input type="checkbox" checked="isSelected"}}{{/if}}
<td>{{#link-to 'warranty.edit' warranty.id class='btn btn-success btn-xs'}}Edit{{/link-to}}<button class="btn btn-danger btn-xs" {{action "deleteWarranty" warranty}}>Delete</button></td>
<td>{{warranty.id}}</td>
<td>{{warranty.claimStatus}}</td>
<td>{{warranty.serialNumber}}</td>
<td>{{warranty.issueDescription}}</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
</div>
// app/controllers/warranty/index.js
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
toggleMultiple() {
this.toggleProperty('canDeleteMultiple');
},
removedSelected: function() {
let selected = this.filterBy('isSelected', true);
console.log(selected);
}
}
});
I have done this way, you can check the twiddle (https://ember-twiddle.com/aa88cd0442ec0d2219e792d58ab8b703?openFiles=templates.index.hbs%2Ctemplates.components.checkbox-component.hbs), same thing as mention by kumkanillam,
in your index.hbs i used checkbox as a component,
{{checkbox-component isChecked=warranty.isSelected action=deleteItems index=index}}{{/if}}
and in controller actions,
removedSelected: function() {
let selected = this.get('model').filterBy('isSelected', true);
console.log(selected);
}
In your hbs file,
{{input type="checkbox" checked=warranty.isSelected }}
OR
<input type="checkbox" checked={{warranty.isSelected}} onchange={{action (mut warranty.isSelected) value="target.checked" }}>
and in your controller,
removedSelected: function() {
let selected = this.get('model').filterBy('isSelected', true);
console.log(selected);
}

Sharing Data Between Models in Ember

I've looked through stack overflow but not found any satisfying answers. Here's my problem.
I have a very simple app that I'm creating using EmberJS just for practice. It's an expense tracking application and basically has 3 sections : 'Friends', 'Expenses' and 'Summary' as shown in the screenshot.
The 'Friends' and 'Expenses' sections are working as they should. They allow me to browse through friends that are stored and enter new ones as well. Same goes with the expenses tab.
But I'm not able to get the summary page to work. I've included the code below for each of the controllers (ie friendsController, expensesController). Please do let me know how I can access information from the expenses model and display it in the summary tab. Thanks a million!
App.FriendsController = Ember.Controller.extend({
isEditing: false,
actions: {
add_friend: function() {
this.set('isEditing',true);
},
cancel: function() {
this.set('isEditing',false);
},
addFriend: function(){
var name = this.get('name');
var scrName = this.get('screenName');
var description = this.get('description');
var newFriend = this.store.createRecord('friend', {
name: name,
screenName: scrName,
description: description
});
this.set('name','');
this.set('screenName','');
this.set('description','');
newFriend.save();
this.set('isEditing',false);
},
}
});
App.ExpensesController = Ember.Controller.extend({
isEditing: false,
actions: {
add_expense: function() {
this.set('isEditing', true);
},
cancel: function() {
this.set('isEditing',false);
},
addExpense: function(){
var date = this.get('date');
var description = this.get('description');
var whoPaid = this.get('whoPaid');
var amount = this.get('amount');
var forWhom = this.get('forWhom');
if(!date.trim()) { return; }
if(!description.trim()) { return; }
if(!whoPaid.trim()) { return; }
if(!amount.trim()) { return; }
if(!forWhom.trim()) { return; }
var newExpense = this.store.createRecord('expense', {
date: date,
description: description,
whoPaid: whoPaid,
amount: amount,
forWhom: forWhom
});
this.set('date','');
this.set('description','');
this.set('whoPaid','');
this.set('amount','');
this.set('forWhom','');
newExpense.save();
}
}
});
Application Template :
<script type="text/x-handlebars">
<div class="container content-wrapper">
<div class="row">
<div class="col-md-12">
<h2>{{#linkTo 'index'}}Expense Tracker{{/linkTo}}</h2>
</div>
<hr>
<div class="nav well col-md-12 master">
<ul>
<li>{{#linkTo 'friends'}}Friends{{/linkTo}}</li>
<li>{{#linkTo 'expenses'}}Expenses{{/linkTo}}</li>
<li>{{#linkTo 'summary'}}Summary{{/linkTo}}</li>
</ul>
</div>
<div class="well col-md-12 detail">
{{outlet}}
</div>
</div>
</div>
</script>
Friends Template :
<script type="text/x-handlebars" id="friends">
{{#if isEditing}}
{{partial newFriend}}
<p>
<button {{action 'cancel'}} class="btn btn-success">Cancel</button>
<button {{action 'addFriend'}} class="btn btn-info">Save</button>
</p>
{{else}}
<p><button {{action 'add_friend'}} class="btn btn-primary">(+) New Friend </button></p>
{{/if}}
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Screen Name</th>
<th>Description</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{{#each model}}
<tr>
<td>{{name}}</td>
<td>{{screenName}}</td>
<td>{{description}}</td>
<td>
<button action 'delete_friend' class="btn btn-danger">Delete</button>
</td>
</tr>
{{/each}}
</tbody>
</table>
</script>
Friends Partial Template (to allow entering new friend) :
<script type="text/x-handlebars" id="_newFriend">
<p> Add New Friend </p>
<table class="table table-bordered">
<tr>
<td><label for="name">Name: </label></td>
<td>{{input type="text" value=name id="name"}}</td>
</tr>
<tr>
<td><label for="screenName">Screen Name: </label></td>
<td>{{input type="text" value=screenName id="screenName"}}</td>
</tr>
<tr>
<td><label for="description">Description: </label></td>
<td>{{input type="text" value=description id="description"}}</td>
</tr>
</table>
</script>
Expenses Template :
<script type="text/x-handlebars" id="expenses">
{{#if isEditing}}
{{partial newExpense}}
<p>
<button {{action 'cancel'}} class="btn btn-success">Cancel</button>
<button {{action 'addExpense' 'addSummary'}} class="btn btn-info">Save</button>
</p>
{{else}}
<p><button {{action 'add_expense'}} class="btn btn-primary">(+) New Expense </button></p>
{{/if}}
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Date</th>
<th>Description</th>
<th>Who paid?</th>
<th>Amount</th>
<th>For whom?</th>
</tr>
</thead>
<tbody>
{{#each model}}
<tr>
<td>{{date}}</td>
<td>{{description}}</td>
<td>{{whoPaid}}</td>
<td>{{amount}}</td>
<td>{{forWhom}}</td>
</tr>
{{/each}}
</tbody>
</table>
</script>
Expenses partial template (to allow new expense) :
<script type="text/x-handlebars" id="_newExpense">
<p> Add New Expense </p>
<table class="table table-bordered">
<tr>
<td><label for="date">Date: </label></td>
<td>{{input type="date" value=date id="date"}}</td>
</tr>
<tr>
<td><label for="description">Description: </label></td>
<td>{{input type="text" value=description id="description"}}</td>
</tr>
<tr>
<td><label for="whoPaid">Who Paid: </label></td>
<td>{{input type="text" value=whoPaid}}</td>
</td>
</tr>
<tr>
<td><label for="amount">Amount: </label></td>
<td>{{input type="text" value=amount id="amount"}}</td>
</tr>
<tr>
<td><label for="forwhom">For Whom: </label></td>
<td>{{input type="text" value=forWhom id="forwhom"}}</td>
</tr>
</table>
</script>
Summary Template :
<script type="text/x-handlebars" id="summary">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Total Expenses</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{name}}</td>
<td>{{totalExpenses}}</td>
</tr>
</tbody>
</table>
</script>
In the route model method you can query for models from others routes, like:
App.SummaryRoute = Ember.Route.extend({
model: function() {
return this.store.find('friends');
}
});
So inside of summary controller you can access the friends using this.get('model')
If you need to return more than one promise, you need to use Ember.RSVP.hash:
App.SummaryRoute = Ember.Route.extend({
model: function() {
return Ember.RSVP.hash({
friends: this.store.find('friend'),
expenses: this.store.find('expense'),
}).then(function(data) {
var friends = data.friends,
expenses = data.expenses;
// calculate the totalExpenses ...
// Fixed for simplicity
return { name: 'foo', totalExpenses: 12 }
});
}
});
So inside of summary controller you can access the friends using this.get('model.friends') and expenses with this.get('model.expenses').
If you have a router structure where your subroute needs to access the model from a parent route, like:
App.Router.map(function() {
this.resource('parent', function() {
this.route('child');
});
});
In the child route you will be able to use modelFor('parent') because the parent route already have your model resolved, for example:
App.ChildRoute = Ember.Route.extend({
model: function() {
return this.modelFor('parent')
}
})

Scope within a template

I use the following template to display a table of all users.
<script type="text/x-handlebars" data-template-name="users">
<table>
{{#each model itemController="user"}}
<tr>
<td>{{lastName}}</td>
<td>
{{#if isNew}}
<button {{action 'save' this}} class="btn btn-small">Save</button>
<button {{action 'discard' this}} class="btn btn-small">Discard</button>
{{else}}
{{#linkTo 'user.edit' this activeClass="disabled" classNames="btn btn-small"}}Edit{{/linkTo}}
{{/if}}
</td>
</tr>
{{/each}}
</table>
{{#unless newUserCreate}}
<p>
{{#linkTo 'users.new' classNames="btn btn-small"}}Create a new user{{/linkTo}}
</p>
{{/unless}}
</script>
Below the table I use a {{#unless newUserCreate}} which I'd like to use within the table too but because of a different scope I can't. How can I fix the following snippet to get it working? The User doesn't have a newUserCreate. Only the Users has.
{{#if isNew}}
{{#unless newUserCreate}}
<button {{action 'save' this}} class="btn btn-small">Save</button>
<button {{action 'discard' this}} class="btn btn-small">Discard</button>
{{/unless}}
{{else}}
{{#linkTo 'user.edit' this activeClass="disabled" classNames="btn btn-small"}}Edit{{/linkTo}}
{{/if}}
app.js
App.UsersRoute = Ember.Route.extend({
model: function() {
return App.User.find();
}
});
App.UsersNewRoute = Ember.Route.extend({
model: function() {
return App.User.createRecord();
},
renderTemplate: function() {
this.render({ into: 'users' });
},
activate: function() {
this.controllerFor('users').set('newUserCreate', true);
},
deactivate: function() {
this.controllerFor('users').set('newUserCreate', false);
}
});

call controller from itemController

If I have an itemController defined like this:
{{#each item in items itemController="item"}}
{{#with item}}
<tr>
<td class="check">
<label {{action selectItem this bubbles="false"}}>
{{description}}
</label>
</td>
</tr>
{{/with}}
The action above will be routed to the itemController.
Is there anyway to override this behaviour and to the main controller?

Action Helper in Ember JS not calling function

<a class="btn btn-primary" href="#" {{action "toggleStatus"}}><i class="icon-plus icon-white"></i> Add Staff</a>
This is in a view template called stafflist.handlebars. The content is as follows
<div class="page-header">
<h3>{{staff.title}} <small>List of users who has access to this application</small></h3>
</div>
<div class="commands pull-right">
sta
<a class="btn btn-primary" href="#" {{action "toggleStatus"}}><i class="icon-user icon-white"></i> {{staff.btnTitle}}</a>
</div>
<div class="pull-left">
<input type="text" class="search-query" placeholder="Search">
</div>
<table class="table table-striped table-bordered">
<thead>
<tr>
<td>NAME</td>
<td>ID</td>
</tr>
<thead>
<tbody>
{{#each staff}}
<tr>
<td>{{this.fname}}</td>
<td>{{this.id}}</td>
</tr>
{{/each}}
</tbody>
</table>
The View file is as below
App.StaffListView = Em.View.extend({
templateName:'sellap-web/~templates/stafflist',
staffBinding:'App.staffController',
toggleStatus: function() {
alert('Hurray');
}
});
When clicking the button, the action is never calling the alert. What is going wrong here. I am using ember-skeleton to compile.
Found the culprit. My App.create has a method called init. I changed the name to something else and now it works fine. I didnt call the super.