Skip to content
Advertisement

How to catch form submit with Backbone.js

When I test and click my apply button after I put in data in my input fields, I get a file not found error.

The Login button is a dummy button with no functionality to it. I want to only display an alert box that says “You logged in as (user name here) Succesfully!!!” after apply is clicked.

var Credentials = Backbone.Model.extend({});

var LoginView = Backbone.View.extend({
  el: $("#login-form"),

  events: {
    "click #login": "login"
  },

  initialize: function(){
    var self = this;

    this.firstname = $("#username");
    this.lastname = $("#lastname");
    this.number = $("#number");
    this.username = $("#username");
    this.password = $("#password");

    this.firstname.change(function(e){
      self.model.set({firstname: $(e.currentTarget).val()});
    });

    this.lastname.change(function(e){
      self.model.set({lastname: $(e.currentTarget).val()});
    });

    this.number.change(function(e){
      self.model.set({number: $(e.currentTarget).val()});
    });

    this.username.change(function(e){
      self.model.set({username: $(e.currentTarget).val()});
    });

    this.password.change(function(e){
      self.model.set({password: $(e.currentTarget).val()});
    });
  },

  login: function(){
    var firstn= this.model.get('firstname');
    var lastn= this.model.get('lastname');
    var numb= this.model.get('number');
    var user= this.model.get('username');
    var pword = this.model.get('password');

    alert("You logged in as " + user + "Succesfully!!!");

    return false;
  }
});

window.LoginView = new LoginView({model: new Credentials()});
});

<form action="/login" id="login-form" align="left">
    <h1> Your Registration Form:</h1>

    First Name <input type="text" id="firstname" placeholder="First Name">
    Last Name <input type="text" id="lastname" placeholder="Last Name">
    Phone No. <input type="text" id="number" placeholder="1(555)555-5555">
    UserName <input type="text" id="username" placeholder="UserName">
    Password <input type="password" id="password" placeholder="Password">

    <button id="login" onclick="">Apply</button>
    <!-- dummy button  -->
    <button id="login-button">Login</button>
</form>

Advertisement

Answer

Why a file not found error?

You get a file not found error because the form is submitted and the action is "/login" with the default method being a GET request, so the submit makes a GET request to the login page but it doesn’t exist on the server. The server returns a File not found error.

How to prevent the submit?

You need to stop the submit with JavaScript. To do that, first catch the submit event, then call .preventDefault() on the submit event object.

How to catch the submit event with Backbone?

Backbone offers the events property on views.

The events hash (or method) can be used to specify a set of DOM events that will be bound to methods on your View through delegateEvents.

The following is the simplest way of catching a submit event, granted the root element of the view is the form, like in your code.

events: {
    "submit": "onSubmit",
},

onSubmit: function(e) {
    // `e` being a standard DOM event
    e.preventDefault();
}

Here I simplified your view:

var LoginView = Backbone.View.extend({
    // Put the string into a template to ease the manipulation later on.
    template: _.template("You logged in as <%= username %> and a password of <%= password %>nFirstName:<%= firstname %>nLastName:<%= lastname %>nNumber:<%= number %>"),
    el: $("#login-form"),

    events: {
        // listen for the submit event of the form
        "submit": "onSubmit",
        // listen to events from here
        "change #username": 'onUsernameChange'
    },

    initialize: function() {
        // it's a good idea to cache jQuery objects like this.
        this.firstname = $("#username");
        this.lastname = $("#lastname");
        this.number = $("#number");
        this.username = $("#username");
        this.password = $("#password");

        // but avoid extensive `change` listeners as it's inefficient and
        // useless in this case. If you want to listen to changes, do it 
        // in the events hash, like the "onUsernameChange" example.
    },

    onSubmit: function(e) {
        // prevent the submit and do what you want instead
        e.preventDefault();

        // Set directly with an object, it's quick and clean.
        this.model.set({
            firstname: this.firstname.val(),
            lastname: this.lastname.val(),
            number: this.number.val(),
            username: this.username.val(),
            password: this.password.val()
        });

        // use the template for the alert.
        alert(this.template(this.model.toJSON()));
    },

    onUsernameChange: function(e) {
        // no need for jQuery for a trivial value retrieval
        console.log(e.currentTarget.value);
    }
});

Specify the form buttons type attribute as it’s submit by default. So making the #login-button a type="button" ensures it won’t trigger a submit.

<button type="submit" id="login">Apply</button>

<!-- dummy button  -->
<button type="button" id="login-button">Login</button>

Why isn’t it working when using the exact code above?

Notice that the root element of the view is specified with the el property.

In your initial code, you’re using jQuery’s core function to find and pass the form element to the view. But for it to work, the form element must exist before running the JS of the view.

So the HTML page structure should look something like this:

<html>
    <head>
        <!-- head stuff like CSS, title, etc.  -->
    </head>
    <body>
        <form id="login-form">
            <!-- rest of the form goes here -->
        </form>

        <!-- Load the scripts here -->
        <script src="libs/jquery/dist/jquery.js"></script>
        <script src="libs/underscore/underscore.js"></script>
        <script src="libs/backbone/backbone.js"></script>

        <!-- then your own code can go here, or into another js file. -->
        <script>
            // your view, etc.
        </script>
    </body>
</html>
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement