Alvaro Pedraza
Alvaro Pedraza

Reputation: 1292

javascript iterate over array of objects

I'm working in an Angular app and inside a controller I need to iterate over an array of objects. This is the controller and the code involved in this situation:

myapp.controller('LoginController', ['$scope',  function(scope) {
    // Users for test
    this.users = [
        {
            name: 'admin',
            password: 'admin',
            role: 'ADMIN'
        },
        {
            name: 'employee',
            password: '12345',
            role: 'EMPLOYEE'
        }
    ];
    console.dir(this.users); // Prints an array of objects correctly

    // called when user submits
    scope.login = function() {
        console.log('login(). User: ');
        console.dir(scope.user); // Prints the object with user's input (also correct)

        var found = false;

        for(let u of this.users) {
            console.log('Comparing with:');
            console.dir(u);

            if(u.name == scope.user.name && u.password == scope.user.password) {
                console.log('Found!');
                found = true;

                // do something else...
            }
        }

        if(!found) { // show error message... }
    }
}]);

The problem is that when I submit the login form (call to scope.login()) I get an error message in the console:

TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
    at m.scope.login (loginController.js:44)
    ...

loginController.js:44 corresponds to for(let u of this.users) { line. I searched through the web (W3 Schools, MDN and this site also) but the solutions didn't worked for me. I already tried the following solutions:

I'm feeling that it's something simple but I cant't figure out what it is (I'm not very skilled in Javascript, sorry). Can anyone help me with this issue?

Thanks in advance for your answers.

Upvotes: 1

Views: 106

Answers (2)

graemeboy
graemeboy

Reputation: 610

The scope is changing within the login function, so the variable this isn't the same before as it is within that function.

Before scope.login = function() { you can write:

var _this = this;

then use _this.users.forEach(function(user) {

or for (var i = 0; i < _this.users.length; i++)

Upvotes: 2

bcr
bcr

Reputation: 3811

The this context changes inside your scope.login = function () {}, as it's an object method, this is a reference to scope. try this:

myapp.controller('LoginController', ['$scope',  function(scope) {
    var that = this; // reference to the correct this context
    // Users for test
    this.users = [
        {
            name: 'admin',
            password: 'admin',
            role: 'ADMIN'
        },
        {
            name: 'employee',
            password: '12345',
            role: 'EMPLOYEE'
        }
    ];
    console.dir(this.users); // Prints an array of objects correctly

    // called when user submits
    scope.login = function() {
        console.log('login(). User: ');
        console.dir(scope.user); // Prints the object with user's input (also correct)

        var found = false;
        for(let u of that.users) { // use the correct context here
            console.log('Comparing with:');
            console.dir(u);

            if(u.name == scope.user.name && u.password == scope.user.password) {
                console.log('Found!');
                found = true;

                // do something else...
            }
        }

        if(!found) { // show error message... }
    }
}]);

Upvotes: 1

Related Questions