Reputation: 131
Just starting out with Ember, I wanted to perform some action when a user types something in a text field. I first tried this
<input type="text" {{bind-attr value=qty}} {{action "checkQty" on="keyUp"}}/>
That correctly initialized the text field's value and called the checkQty()
function in my controller's actions
hash, but I was not getting the updated value for qty
. So it seems bind-attr
is a one-way deal.
I tried using the TextField
view:
{{view Ember.TextField value=qty onEvent="keyPress" action="checkQty"}}
I had to use keyPress
instead of keyUp
because onEvent only allows enter or keyPress. This worked, except that reading qty's value on keyPress
gives me the value of the field before the user pressed the key and not afterward.
So I wound up using the input helper to specify the field:
{{input type="text" value=qty}}
And created an observer in my controller:
checkQty: function() {
Ember.Logger.log('qty: ', this.get('qty'));
}.observes('qty').on('change')
So that works, but now I am confused about best practices for architecting my Ember app. It seems like the prescribed method is for your template to effectively call actions on your controller. My usage of an observer feels like a hack to get around my failure to get this working in a template.
After looking at the Ember source code, I was able to extend TextField
to get the behavior I wanted:
MyApp.TextField = Ember.TextField.extend({
keyUp: function(event) {
this.sendAction('action', this.value);
}
});
And my template then became:
{{view MyApp.TextField value=qty onEvent="keyUp" action="checkQty"}}
Is there a better way to accomplish this in Ember?
Upvotes: 2
Views: 5773
Reputation: 268
This can also be accomplished within the route of a template, or better yet, within a component using key-up="actionname".
Handling the data of the input field (and any others associated with it) within a component will utilize Ember's defaults instead of adding new logic and simply allow for handling the data returned.
//.js
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
checkQty(q) {
console.log(q);
}
}
});
//.hbs
{{input type="text" key-up="checkQty"}}
You could take it a step further if you need to edit the qty on the input within your action by binding it to a property.
// .js
import Ember from 'ember';
export default Ember.Component.extend({
qty: 0,
actions: {
checkQty(q) {
console.log(this.get(qty));
}
}
});
// .hbs
{{input type="text" value=qty key-up="checkQty"}}
Upvotes: 1
Reputation: 84
You need to utilize the sendAction method, here is an example
# coffeescript code sample
window.App = Ember.Application.create()
# define the keyupaction callback on all TextField views
Em.TextField.reopen
keyUp: (e) ->
@sendAction('keyUpAction', e)
# the keyup callback specific for each controller
App.ApplicationController = Em.Controller.extend
actions:
foobar: ->
console.log 'do yor validation here'
# the text field view
{{view Em.TextField valueBinding="firstName" keyUpAction="foobar"}}
Upvotes: 6