Circular bindings and transforms
by machty
HTML
<script src="https://github.com/downloads/wycats/handlebars.js/handlebars-1.0.0.beta.6.js"></script>
<script src="https://github.com/downloads/emberjs/ember.js/ember-1.0.pre.js"></script>
<script type="text/x-handlebars" data-template-name="application">
Foo is: {{App.number}}<br/>
{{view Em.TextField valueBinding="App.moneyAsString"}}: vanilla Em.TextField<br/>
{{view App.SlowTextField valueBinding="App.moneyAsString"}}: only updates on `change` event (losing focus)<br/>
<input type="text" {{bindAttr value="App.moneyAsString"}}/>: raw input field with bindAttr value, can only respond to changes to App.number, can't cause them.<br/>
</script>
CSS
body {
font-size: 13px;
font-family: Arial, sans-serif;
}
JavaScript
App = Ember.Application.create({
money: 1.23,
// Formats numeric 'money' property as
// 2-decimal string, and converts
// strings to valid money.
moneyAsString: function(key, value) {
//console.log("(" + key + ", " + value + ")");
var isSet = arguments.length === 2;
if(!isSet) { value = this.get('money'); }
// Stringify, remove non number characters...
value = value.toString().replace(/[^0-9.]/g, '');
// Make it a number.
value = parseFloat(value);
if(isNaN(value)) { value = 0; }
// We've done everything we can to make sure it's a valid number.
// If we're setting, now is the time to do it.
if(isSet) { this.set('money', value) }
// Whether it's get or set, we need to return the stringified
// version of the valid number.
return value.toFixed(2);
}.property('money')
});
App.ApplicationView = Ember.View.extend({
templateName: "application"
});
App.ApplicationController = Ember.Controller.extend();
App.SlowTextField = Ember.TextField.extend({
// Override this method defined in TextSupport mixin.
interpretKeyEvents: function(event) {
var map = Ember.TextSupport.KEY_EVENTS;
var method = map[event.keyCode];
// Disabling this means the value only gets
// propagated once the field loses focus.
// this._elementValueDidChange();
if (method) { return this[method](event); }
},
focusOut: function() {
this.get('valueBinding').fromDidChange(this);
// fromDidChange: function(target) {
//this._scheduleSync(target, 'fwd');
//},
//console.log("ASASD");
//this.notifyPropertyChange('value');
//this.set('value', 'barf');
//debugger;
}
});
App.Router = Ember.Router.extend({
root: Ember.Route.extend()
});
App.initialize();