If I define a checkbox as follows:
{{input type="checkbox" name="email" checked=controller.isEmailChecked}} Email
In the callback controller.isEmailedChecked, defined as:
isEmailChecked: function(key, value) {
...
}
How do I get the value of name ("email")?
My controller is responsible for displaying multiple checkboxes so I do not want to have to write lines like this:
{{input type="checkbox" name="x" checked=controller.isXChecked}} X
{{input type="checkbox" name="y" checked=controller.isYChecked}} Y
Only to be doing:
ixXChecked: function(key, value) {
// Set or Get
this.set('x', value);
this.get('x');
}
ixYChecked: function(key, value) {
// Set or Get
this.set('y', value);
this.get('y');
}
Can someone point me to the docs please.
Edit: Same applies to actions on Buttons:
<button {{action 'toggleSetting'}}>
</button>
How would I get the name of the element in the toggleSetting callback?
Thanks a lot,
Thanks albertjan but this is more simple:
{{view Ember.Checkbox checkedBinding=someModelProperty}}
It updates the someModelProperty when clicked, and it also sets the correct value initially.
You can pass a parameter to a action like this: {{action "post" "test"}} where the second test can also be a variable. {{action "post" mail}}
As for the checkboxes I'd solve that with an item controller:
{{#each thing in things itemController='thing'}}
{{input type="checkbox" checked=onChecked}}
{{/each}}
and your controller would looks something like:
App.ThingController = Ember.Controller.extend({
needs: ['parent'] //where parent is the name of your other controller.
action: {
isChecked: function() {
this.get('contollers.parent')
.send('checkboxChecked', this.get('model.name'));
}
}
});
Or you can add a component, lets call it named-checkbox. And that would look something like this:
Template (app/templates/components/named-checkbox.hbs):
{{input name=name type="checkbox" checked=onChecked}}
{{yield}}
Component (app/components/named-checkbox.js):
import Ember from 'ember';
import layout from '../templates/components/named-checkbox';
export default Ember.Component.extend({
layout: layout,
name: "",
action: {
onChecked: function() {
this.sendAction(this.get('action'), this.get('name'));
}
}
});
Then you can use it like this:
{{named-component name="email" action=isChecked}}
This will result in the isChecked action being called on the controller with the name as it's attribute:
actions: {
isChecked: function(name) {
this.set('name', !this.get('name'))
}
}
Related
template
{{input type="email" value=email placeholder="email"}}
<button {{action "addUser"}} type="submit">Add</button>
controller
export default Controller.extend({
actions: {
addUser: function(){
//some codes here
$.ajax({
//some codes here
}).then(()=>{
alert("success");
});
}
}
});
When I call press the button and call the function addUser I need to disable the button until the whole function is finished execution
Please help..!
There are two ways of doing that.
First - maintain state manually
This means you should have a property on your controller and set it to true when task is running
export default Controller.extend({
actions: {
addUser: function(){
this.set('addUserRunning', true);
//some codes here
$.ajax({
//some codes here
}).then(()=>{
alert("success");
}).always(() => {
this.set('addUserRunning', false);
});
}
}
});
{{input type="email" value=email placeholder="email"}}
<button type="submit" disabled={{addUserRunning}} {{action "addUser"}}>Add</button>
Second (recommended by me) - use ember-concurrency
There is an addon called ember-concurrency. You need to look through the docs to understand how to use it. Instead of action you will use task and task has properties for it's state.
It will be something like this:
import { task } from 'ember-concurrency';
export default Controller.extend({
addUser: task(function* () {
//some codes here
yield $.ajax({
//some codes here
});
alert("success");
}).drop()
});
{{input type="email" value=email placeholder="email"}}
<button type="submit" disabled={{addUser.isRunning}} onclick={{perform addUser}}>Add</button>
I have a few actions that I'm placing on each item in a loop. Currently the action reveals all of the book-covers, instead of just one I want to target.
http://guides.emberjs.com/v2.0.0/templates/actions
Looks like I can pass a parameter, but I'm not sure of the syntax.
I've done this before in earlier version and remember using this or should it be
{{action 'showCover' book}} ... ?
Controller
import Ember from 'ember';
export default Ember.Controller.extend( {
actions: {
showCover(book) { // ?
this.set('coverVisible', true); // or
this.toggleProperty('coverVisible');
},
...
}
});
other thoughts...
actions: {
showCover(book) {
// currently this is just setting the *route in general* to coverVisible:true - which is not what I want
this.set('coverVisible', true);
// I can see this class - the route...
console.log(this);
// I can see the model of this route...
console.log(this.model);
// and I can see the book object...
console.log(book);
// but how do I set just the book object???
// I would expect book.set('property', true) etc.
console.log(book.coverVisible);
console.log(this.coverVisible);
}
}
Template
{{#each model as |book|}}
<li class='book'>
<article>
{{#if book.coverVisible}}
<figure class='image-w book-cover'>
<img src='{{book.cover}}' alt='Cover for {{book.title}}'>
</figure>
{{/if}}
...
{{#if book.cover}}
{{#unless book.coverVisible}}
<div {{action 'showCover'}} class='switch show-cover'>
<span>Show cover</span>
</div>
{{/unless}}
{{/if}}
{{/each}}
ALSO - please suggest a title for this if you can think of a more succinct one.
http://ember-twiddle.com/f44a48607738a0b9af81
#sheriffderek, You have already provided the solution in your question itself. You can pass the additional parameters after the action name. Something like:
<button {{action "showCover" book}}>Show Cover </button>
Working example using ember-twiddle: http://ember-twiddle.com/e7141e41bd5845c7a75c
You should be calling book.set('coverVisible', true); as you are wanting to set the property on the book itself.
actions: {
showCover: function(book) {
book.set('coverVisible', true);
}
I want to get the value of the textarea to use inside my route. I tried using the method below, but the alert shows 'undefined' for that value. How would I go about getting the value of the textarea from the route? I am running the latest version of ember-cli.
Template
{{textarea type="text" value='name'}}
<button {{action 'submit'}} >Send</button>
Route
actions: {
submit: function() { alert(this.get('name'));
} }
You have to pass a variable through action submit, which is bound to textarea value. Usually such a variable is defined in controller (or in wrapper component).
//template
{{textarea type="text" value=name}}
<button {{action 'submit' name}} >Send</button>
//controller
name: 'defaultName'
//route
actions: {
submit: function(val) {
alert(val);
}
}
Working jsbin here
I am new to Ember and am trying to do a simple create / delete user. I am able to create a client, but can not delete them?
Client Controller:
export default Ember.ArrayController.extend({
actions: {
createClient: function(newName) {
// Create the new Todo model
var client = this.store.createRecord('client', {
name: newName,
avgMarkup: 2,
quotes: 1
});
// Clear the "New client" text field
this.set('newName', '');
// Save the new model
client.save();
}
}
});
I've then tried adding this:
destroyRecord: function() {
this.get('model').destroyRecord();
}
And I have no luck. My view is this:
<ul id="client-list">
<h6>Clients Name:</h6>
{{input type="text" id="new-client" placeholder="Please enter client name"
value=newName action="createClient"}}
{{#each}}
<li>
<input type="checkbox" class="toggle">
<label>{{name}}</label>
<button {{action "destroyRecord" }} class="destroy"></button>
</li>
{{/each}}
</ul>
Is this doable with an Array Controller?
Thanks
To remove the respective user just pass it to your destroyRecord action:
In your template pass thiswhich correspond to the current user being iterated:
<button {{action "destroyRecord" this}} class="destroy">Destroy</button>
And then when someone click in destroy button, model will be the current user:
destroyRecord: function(model) {
model.destroyRecord();
}
I want to display an input field, and immediately autofocus it upon clicking a button. Im still new to Ember so i am not sure this is the correct approach, but I tried to wrap as an ember component
template
{{#if showCalendarForm}}
{{new-calendar focus-out='hideNewCalendar' insert-newline='createCalendar'}}
{{else}}
<button class="btn btn-sm btn-primary" {{action "showNewCalendar"}}>New</button>
{{/if}}
new-calendar component handlebars:
<div class="input-group">
{{input
class = 'form-control'
id = 'newCalendar'
type = 'text'
placeholder = 'New calendar'
value = calendarName
action = 'createCalendar'
}}
</div>
new-calendar component js
import Ember from 'ember';
export default Ember.Component.extend({
didInsertElement: function() {
this.$().focus();
}
});
When I click the button, the text field is displayed, but autofocus and hitting enter doesnt work
The way the jQuery is written, you are trying to set focus on the <div class="input-group">, try this instead:
didInsertElement: function() {
this.$('input').focus();
}
Another way to do this would be to extend the Ember.TextField:
export default Ember.TextField.extend({
becomeFocused: function() {
this.$().focus();
}.on('didInsertElement')
});
Then, in your new-calendar template, use this component:
{{focus-input
class = 'form-control'
id = 'newCalendar'
type = 'text'
placeholder = 'New calendar'
value = calendarName
action = 'createCalendar'
}}
This way you can reuse the focus-input component wherever you need to.
As for hitting enter to create the calendar, I think you want to listen for the keyPress event, check to see if it's the enter key, and then send the action rather than trying to use insert-newline='createCalendar'.
//in FocusInputComponent
keyPress: function(e) {
// Return key.
if (e.keyCode === 13) {
this.sendAction();
}
}
Try wrapping your focus call in an Ember.run and schedule it to be run in the after render queue like this:
didInsertElement: function()
{
Ember.run.scheduleOnce('afterRender', this, function() {
this.$().focus();
});
}
this blog post has helped me a lot in understanding ember's lifecycle hooks:
http://madhatted.com/2013/6/8/lifecycle-hooks-in-ember-js-views