[Note: This post uses Ember master syntax. On 0.9.8.1, you may have to remove
view. in the *Binding attributes.]

Live Updating

Ember.TextField and
friends live-update their value property as the user enters text. You can use
valueBinding to bind to some model property, like so:

1
{{view Ember.TextField valueBinding="firstName"}}

Now firstName will be updated immediately as the user enters text.

With Save button

Oftentimes, live updating is not what you want. Instead, you want to update the
model data only when the user clicks a Save button.

Plain input field

1
2
3
4
5
6
7
8
App.LazyTextField = Ember.View.extend({
  attributeBindings: ['value', 'type', 'size', 'name', 'placeholder', 'disabled', 'maxlength'],
  tagName: 'input',
  type: 'text',
  getCurrentValue: function() {
    return this.$().val();
  }
});

This is a lazy-updating text field. Whenever you set or update its value
property, the contents get updated, but when the user changes the contents,
they are not written back into value.

Now we can implement a save button like so:

1
2
3
4
5
6
7
8
9
10
11
12
App.PersonView = Ember.View.extend({
  firstName: 'Jane',
  template: Ember.Handlebars.compile(
    '<form>' +
    '{{view App.LazyTextField valueBinding="view.firstName" viewName="textField"}}' +
    '<input type="submit" value="Save" {{action save}}>' +
    '</form>'),
  save: function(e) {
    e.preventDefault(); e.stopPropagation();
    this.set('firstName', this.get('textField').getCurrentValue());
  }
});

Another pattern: One-way bindings

There is another way to achieve this, using the built-in live-updating
Ember.TextField and a one-way binding. It’s more compact, though slightly
more opaque:

1
2
3
App.LazyTextField = Ember.TextField.extend({
  valueBinding: Ember.Binding.oneWay('source')
});

Now instantiate LazyTextField, and bind your model data to source instead of
value, and property changes will propagate only from source to value, but
not vice versa (unless explicitly copied by the save function).

1
2
3
4
5
6
7
8
9
10
11
12
App.PersonView = Ember.View.extend({
  firstName: 'Jane',
  template: Ember.Handlebars.compile(
    '<form>' +
    '{{view App.LazyTextField sourceBinding="view.firstName" viewName="textField"}}' +
    '<input type="submit" value="Save" {{action save}}>' +
    '</form>'),
  save: function(e) {
    e.preventDefault(); e.stopPropagation();
    this.set('firstName', this.getPath('textField.value'));
  }
});

Read more at the source