Reputation: 400
I'm trying to create a manually saved form with a moderate number of fields (let's say 20) in Ember.js (not using live bindings) and so far am confused about the correct way / best practice for doing so. I've found the following methods:
http://www.solitr.com/blog/2012/06/ember-input-field-with-save-button/
How to use one-way binding on emberjs?
https://stackoverflow.com/a/16473186/1248965
All of the above methods seem hacky to a degree; they either extend the text field or use a per-field observer, requiring you to list out each one. Is there some other way? Something like the 'unbound' helper, but allowing the auto-model updating magic / validation (via ember-data) on some action (like an 'unbound-until' or 'conditional-bind' or something)? I've gone through all the docs, SO, the github issues, the Ember forum, and the links above, and still feel like I must have missed something.
Basically, a way to say "do everything you would do with a normally bound form/fields, but only on a certain action, rather than in real time."
Upvotes: 1
Views: 720
Reputation: 6709
What you want is a "Buffered Proxy", where you temporarily store all changes to the model (you can catch those using setUnkownProperty
) in a proxy object. Once you are happy with the changes, you'd copy all of the proxy data over into the actual object ("flush the data").
App.Heisenberg = {
firstName: 'Walter',
lastName: 'White',
};
App.IndexRoute = Ember.Route.extend({
model: function() {
return App.Heisenberg;
},
setupController: function(controller, model) {
controller.set('content', model);
}
});
App.IndexController = Ember.ObjectController.extend({
proxy: {},
setUnknownProperty: function(key, value) {
console.log("Set the unknown property: " + key + " to: " + value);
this.proxy[key] = value;
console.log(this.proxy);
},
flush: function() {
for(var key in this.proxy)
this.set('model.'+key, this.proxy[key]);
}
});
Template:
<script type="text/x-handlebars" data-template-name="index">
Saved Name: {{firstName}} {{lastName}}<br />
<br />
<form {{ action "saveEdit" on="submit" }}>
First Name: {{input type="text" valueBinding="firstName"}}<br />
Last Name: {{input type="text" valueBinding="lastName"}}<br />
<br />
<button {{ action "flush" }}>Flush</button>
</form>
</script>
This would make for a nice controller Mixin.
See this jsBin for a live example.
Upvotes: 3
Reputation: 400
I found a workaround, but I'm not 100% happy with it:
In my "editing" template, I have:
<form {{ action "saveEdit" on="submit" }}>
Title: {{input type="text" value=title}}
<input type="submit" value="Save">
<button {{ action "cancelEdit" }}>Cancel</button>
</form>
Then in my associated controller, I do:
cancelEdit: function() {
var entry = this.get('model');
this.set('isEditing', false);
entry.rollback();
},
saveEdit: function() {
var entry = this.get('model');
this.set('isEditing', false);
entry.save().then(
function() {
console.log('Saved!');
}
I simply hide the fields where the "live updating" would show. I still would like to find a way to temporarily turn off the binding until I trigger my "saveEdit" action, since this still seems inelegant.
Upvotes: 0