skip to Main Content

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

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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')
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search