Search code examples
javascriptbackbone.js

Comparing value from input with backbone collection data


I'm trying to create very simple login with backbonejs. Collection stores usernames and passwords. Login view has two inputs and on click it should perform check function and compare input value with data from collection.

Html part looks like this:

<div class="login-block">
  <script type="text/template" id="start">
    <form id="login">
      <div class="input-wrapper"><input type="text" placeholder="Username" id="username" required></div>
      <div class="input-wrapper"><input type="password" placeholder="Password" id="password" required></div>
      <div class="input-wrapper"><button class="btn">Sign in!</button></div>
    </form>
  </script>

  <div class="error" class="block">
       Error
  </div>

  <div class="success">
      Success
  </div>
</div>

Here is my Js code:

var User = Backbone.Model.extend({
    defaults: {
      login: 'root',
      mail: '[email protected]',
      password: ''
    }
});

var user = new User();

//variable to store username

var loginData = {
    username: "",
    password: ""
}

// userbase
var UserCollection = Backbone.Collection.extend({
    model: User
});



var userCollection = new UserCollection([
  {
   username: 'Ivan',
   mail: '[email protected]',
   password: '1234'
  },
  {
   username: 'test',
   mail: '[email protected]',
   password: 'test'
  }
 ]);

// login page

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

    events: {
      "click .btn": "check"
    },

    check: function(){
      loginData.username = this.$el.find("#username").val(); // store username
      loginData.password = this.$el.find("#password").val();// store password
          if (loginData.username === userCollection.each.get("username") && loginData.password === userCollection.each.get("password")) 
              {appRouter.navigate("success", {trigger: true});
          }else{
              appRouter.navigate("error", {trigger: true});
              } 
      },

      render: function () {
        //$(this.el).html(this.template());
          var template = _.template($('#start').html())
          $(this.el).html(template());
          //template: template('start');
          return this;
      }
}); 

var loginView = new LoginView({collection: userCollection});

var AppRouter = Backbone.Router.extend({
    routes: {
       '': 'index', // start page
       '/error': 'error',
       '/success': 'success'
    },

    index: function() {
         loginView.render();
         console.log("index loaded");
    }, 

    error: function(){
      alert ('error');
    },

    success: function(){

      console.log('success');
    }


});

var appRouter = new AppRouter();

Backbone.history.start();

It works fine to the check function, and it stores username and password, but something is clearly wrong either with router or check function when it starts comparison. Instead of routing to success or error page, it rerenders index page.

P.S I didn't use namespacing and code in general is not of a greatest quality, but it was made for educational purpose only.


Solution

  • You have to add the attribute type="button" to your button, otherwise it will submit the form when clicked (See this question):

    <script type="text/template" id="start">
      <form id="login">
        <div class="input-wrapper"><input type="text" placeholder="Username" id="username" required></div>
        <div class="input-wrapper"><input type="password" placeholder="Password" id="password" required></div>
        <div class="input-wrapper"><button class="btn" type="button">Sign in!</button></div>
      </form>
    </script>
    

    You can also return false in the click event handler, which would cancel the default action. (submitting the form, if you don't add type="button").

    For comparing the values with the hardcoded collection, you can't call each as you where doing (which is an iteration function provided by Underscore) because you would receive an error. You could use Underscore's findWhere method which is also available in Backbone collections. So the click event handler (Your check function) could look like this:

    check: function(){
        loginData.username = this.$el.find("#username").val(); // store username
        loginData.password = this.$el.find("#password").val();// store password            
        if(userCollection.findWhere({username: loginData.username, password: loginData.password})){
            appRouter.navigate("success", {trigger: true});
        }else{
            appRouter.navigate("error", {trigger: true});
        } 
        return false;
    },
    

    You can try it on this fiddle