Node.JS Node.JS - 28 days ago 8
HTML Question

How to avoid GET request on form submit with Backbone

I am trying to write a editable table using Backbone.js.

This is my Backbone.js app:

<!DOCTYPE html>
<html lang="en">

<head>
<title>Resume builder!</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>

<style>
.jumbotron {
height: 100vh;
}

body {
background-color: white !important;
}

.table-bordered th,
.table-bordered td {
border: 1px solid #ddd!important
}
</style>

</head>

<body>

<div class="jumbotron">
<div class=container>
<h1>Resume builder</h1>

<table class="table table-bordered">
<thead>
<tr>
<th>Degree</th>
<th>Starting date</th>
<th>Ending date</th>
<th>Details</th>
</tr>
</thead>

<tbody id="informations">
<script type="text/template" id="info-row">
<tr>
<td>
<%=title%>
</td>
<td>
<%=start%>
</td>
<td>
<%=end%>
</td>
<td>
<%=details%>
</td>
<td>
<botton class="btn btn-primary" data-action="modify">edit</botton>
<botton class="btn btn-danger" data-action="delete">delete</botton>
</td>
<tr>
</script>

</tbody>
</table>

<div id="actions">
<botton class="btn btn-primary" id="addInformation">Add information</botton>
</div>


<script type="text/template" id="info-modify">
<div class="modal fade" id="edit-modal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">INFORMATION</h4>
</div>
<div class="modal-body">
<form role="form">
<div>
<div class="radio">
<label><input type="radio" data-type="education" name="type" <%= (type == "education") ? "checked" : ""%>> Education</label>
</div>

<div class="radio">
<label><input type="radio" data-type="experience" name="type" <%= (type == "experience") ? "checked" : ""%>> Experience</label>
</div>
</div>

<div class="form-group">
<label>Title for Degree or experience (e.g. Computer Sci. | Software dev.):</label>
<input type="text" class="form-control" value="<%=title%>" name="title">
</div>

<div class="form-group">
<label>Start date:</label>
<input type="number" class="form-control" value="<%=start%>" name="start">
</div>

<div class="form-group">
<label>End date:</label>
<input type="number" class="form-control" value="<%=end%>" name="end">
</div>

<div class="form-group">
<label>Details:</label>
<textarea rows="5" class="form-control" name="details"><%=details%></textarea>
</div>

<button type="submit" class="btn btn-success">Submit</button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</script>

</div>
</div>

<div id="modal">
</div>

</body>

<script>
$(function() {
var baseModalView = Backbone.View.extend({
el: $("#modal"),
className: 'modal fade hide',
template: _.template($("#info-modify").html()),
events: {
'hidden': 'teardown',
"click [type='submit']": "notify"
},
initialize: function() {
_.bindAll(this, "show", "teardown", "render", "notify");
this.render();
this.show();
},
show: function() {
this.$el.modal('show');
},
teardown: function() {
this.$el.data('modal', null);
this.remove();
},
render: function() {
this.$el.empty();
this.setElement(this.template(this.model.toJSON()));
},
notify: function() {
var self = this;
this.model.set({
type: self.$el.find("[type='radio']:checked").data("type"),
start: self.$el.find("[name='start']").val(),
end: self.$el.find("[name='end']").val(),
details: self.$el.find("textarea").text()
});
}
});

var InformationModel = Backbone.Model.extend({
id: -1,
defaults: {
type: " ",
title: " ",
start: 2015,
end: 2016,
details: " "
}
});

var InformationView = Backbone.View.extend({
events: {
"click [data-action='modify']": "modifyInformation",
"click [data-action='delete']": "deleteInformation"
},
template: _.template($("#info-row").html()),
initialize: function() {
_.bindAll(this, "render", "modifyInformation", "deleteInformation");
this.render();
},
render: function() {
this.setElement(this.template(this.model.toJSON()));
},
modifyInformation: function() {
var self = this;
modalView = new baseModalView({
model: self.model,
template: _.template($("#info-modify").html())
});
},
deleteInformation: function() {
this.model.destroy();
}
})

var InformationCollection = Backbone.Collection.extend({
url: "../dummy/",
model: InformationModel
});

var InformationsView = Backbone.View.extend({
el: $("#informations"),
initialize: function() {
_.bindAll(this, "render", "addInformation");
var self = this;
this.collection = new InformationCollection();

this.collection.bind("all", this.render, this);

this.collection.fetch();

// I know this is not a Backbone way...
$("#addInformation").on("click", function() {
self.addInformation();
});
},
render: function() {
this.$el.empty();
this.collection.each(function(information) {
var informationView = new InformationView({
model: information
});
this.$el.append(informationView.el);
}, this);
},
addInformation: function() {
var self = this;
modalView = new baseModalView({
model: new InformationModel()
});
}
});


new InformationsView();

$("form").submit(function(e) {
e.preventDefault();
return false;
});
});
</script>

</html>


Question:

After I
edit
a table row and click on submit, Backbone send a strange
GET
request.

enter image description here

Answer

The form is being submitted when you press the submit button.

This code

$("form").submit(function(e) {
            e.preventDefault();
            return false;
        });

Won't actually stop this from happening, as when this code is executed, the form doesn't yet exist in the dom. It's only added when you create that modal view.

This is not tested, but a quick fix should be to:

$(document).on("submit", "form", function(e) {
            e.preventDefault();
            return false;
        });

This will respond to all "submit" events on the page, and then check if they belong to a "form" element before processing the function.

Another solution, which I think is preferable as all functionality is encapsulated in your view, is to replace the submit button with a regular button in the modal template.

<button type="button" class="btn btn-success">Submit</button>

This should stop the submit event from firing, but you'll need to change the action handler the top of the baseModalView view.

Comments