1

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: 'root@mail.com',
      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: 'ivan@mail.com',
   password: '1234'
  },
  {
   username: 'test',
   mail: 'test@mail.com',
   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.

Huangism
  • 16,278
  • 7
  • 48
  • 74
vitalym
  • 893
  • 6
  • 12
  • 29

2 Answers2

4

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

Community
  • 1
  • 1
Daniel J.G.
  • 34,266
  • 9
  • 112
  • 112
0

The logic check you're doing doesn't look like it would work to me. I would expect the following to generate an error:

userCollection.each.get('username')

the function you're calling on your collection, each, is a wrapped underscore method which takes a function callback as a parameter. If you want to check your username and password, I'd do something like this:

var user = userCollection.findWhere({ username: loginData.userName });

This will return you the model where the username matches. Then you can check the password of that model:

if (user.get('password') === loginData.password) {
  // do something
} else {
  // do something else 
}

EDIT Heck, you can do both checks at once:

var user = userCollection.findWhere({ username: loginData.userName, password: loginData.password });

I'll leave the previous code up just to demonstrate.

kinakuta
  • 9,029
  • 1
  • 39
  • 48