I have a simple view that binds itself to redraw when the model changes as most guides indicate:
this.model.bind('change', this.render, this);
This view has a form with an input box and a submit button. I am binding to the 'change' event of the input box to change the related item on the model. (I can do this manually or with the ModelBinder project, works the same either way.)
A user changes the value in the form input box, then clicks on the submit button. The model is updated, the view and form are re-rendered. The submit button's click event is squashed.
I'm using Backbone's events property:
events : {
'submit form' : 'save'
},
I know that the event is getting ignored because the DOM element that was clicked on is no longer there. I can place a small setTimeout inside of render() to prevent the HTML from being swapped out and things work as expected, but this requires a wait.
I can't be the first person to struggle with this - what's the standard way of capturing form 'change' events, updating the model, and redrawing the view without losing some key click or keypress information?
Similarly if I have several form items the user is unable to tab between the items after changing the contents as the form is redrawn.
Still trying to find a good solution. Things I've tried:
One of the comments asked for some code. I've massively simplified the code into one page and included it below. The actual application is much more complicated. With code as simple below I could just manually re-render parts of the page on change. In the actual application I'm using dustjs templates and even if I don't re-render the form, but do re-render elements that contain the form I have issues clicking on the submit. I'm hoping for a 'pattern' that is typical for backbone applications, including complicated pages and models and forms.
Most of the 'demo' apps and even the sites that I've seen using backbone appear to be mostly presentation focused apps that don't actually gather a lot of input from the user. If you know of a good data-collection focused application/demo based on backbone that would be helpful.
Code:
<!doctype html>
<html lang="en">
<head>
<script src="libs/jquery.js"></script>
<script src="libs/underscore.js"></script>
<script src="libs/backbone.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/template" id="edit_user_template">
<h3>Edit User <%=id%> : <%=name%></h3>
<form>
Name: <input type="text" name="name" value="<%=name%>"><br/>
Email: <input type="text" name="email" value="<%=email%>"><br/>
<input type="submit">
</form>
</script>
<script>
var UserModel = Backbone.Model.extend({});
var model = new UserModel({id: '1', name:'Joe', email:'[email protected]'});
var UserView = Backbone.View.extend({
events : {
'submit form' : 'save',
'change input' : 'inputChange'
},
initialize: function(){
this.model.bind('change', this.render, this);
},
render: function(){
var template = _.template($('#edit_user_template').html(), this.model.toJSON());
this.$el.html(template);
},
inputChange : function(evt){
var target = $(evt.currentTarget);
this.model.set(target.attr('name'), target.val());
},
save : function(event){
console.log('saving');
event.preventDefault();
//this.model.save();
}
});
var view = new UserView({model: model, el: '#container'});
view.render();
</script>
</body>
</html>
You ask for a pattern in backbone. The pattern is to use models to hold form info (like you are doing) and then update specific elements on the page instead of re-rendering everything every time the model changes. ModelBinder offers a nice way to do all of that (https://github.com/theironcook/Backbone.ModelBinder).
I don't think you are going to find a way around not being able to submit a form that doesn't exist anymore. You need to accomplish what you want in a different way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With