简体   繁体   中英

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.

在此处输入图片说明

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.

If you have a form in a Backbone view, handle the form in that view, without global jQuery events .

Say you have this simple view template:

<div id="test-view">

    <form id="test-form">
        <input type="text" name="test">
        <button type="submit">Submit</button>
    </form>
</div>

Then the view only needs to catch the submit for its form:

var FormView = Backbone.View.extend({
    events: {
        "submit #test-form": "onSubmit"
    },
    onSubmit: function(e) {
        e.preventDefault();
        console.log("test-form submit prevented");
    }
});

var view = new FormView({
    el: $('#test-view')
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM