Octtavius Octtavius - 6 months ago 8
AngularJS Question

Cannot read 'xyxyx' property of undefined even if element exist

I have two HTML inputs (

type="email"
,
type="number"
) and my Angular app watches them using
$formatters
and
$parsers
. The errors are stored in an array and when user insert an email which contains "@gmail" the error is removed from the array.

app.controller('form1Controller', function($scope, UserService) {
$scope.formCompleted = false;
$scope.errors = UserService.errors;

//handle the user email input.
$scope.storeEmailErr = function(data) {

var correctKey = "@gmail";
var key = "#userEmail";

var res = {};

if (data != null) {
res = $scope.handleError(data, emailIn, correctKey, key, $scope.errors);
$scope.errors = res[0];
UserService.errors = res[0];
emailIn = res[1];
}
};

//handle the user email input.
$scope.storeIdErr = function(data) {

var correctKey = "0000";
var key = "#userId";

var res = {};

if (data != null) {
res = $scope.handleError(data, idIn, correctKey, key, $scope.errors);
$scope.errors = res[0];
idIn = res[1];
}

};
}


This is the code that adds and removes errors from array. And here i suppose is the problem

function theIndexOf(val) {
console.log("find index in array of length: " + errorsDescription.length)
for (var i = 0; i < errorsDescription.length; i++) {
if (errorsDescription[i].selector === val) {
return i;
}
}
}

app.run(function($rootScope){
$rootScope.handleError = function(data, elemIn, correctKey, key, errorArray){
var idx = theIndexOf(key);
console.log("get index >>>>> " + idx);
var obj = errorsDescription[idx];

//if user didn't put correct word i.e. @gmail or 0000
if (data.indexOf(correctKey) < 0) {
if (!elemIn) {
errorArray.push(obj);
elemIn = true;
}
} else {
if (elemIn) {
$.each(errorArray, function(i){
if(errorArray[i].selector === key) {
errorArray.splice(i, 1);
elemIn = false;
}
});
}
}
return [errorArray, elemIn];
}
});


The problem is that when I insert i.e. "test@gmail.com", the error is deleted from the array and when I insert correct data again it tells me that cannot read 'yyy' property of undefined.

Here is my plunker.
https://plnkr.co/edit/l0ct4gAh6v10i47XxcmT?p=preview

In the plunker, type in the fields 'test@gmail' and test0000 for the Number, then remove data then insert again the same data to see the problem

Any help would be much appreciated!

Answer

EDIT: Working plunkr here: https://plnkr.co/edit/8DY0Cd5Pvt6TPVYHbFA4

The issue is here:

var obj = errorsDescription[idx];

//if user didn't put correct word i.e. @gmail or 0000
if(data.indexOf(correctKey) < 0){
    // console.log("You must put correct word");
    if(!elemIn){
        errorArray.push(obj);
        elemIn = true;
    }
}

When your Personal Number error is removed, the logic above pushes undefined to your errorArray (because elemIn is false). Your storeIdErr methond:

$scope.storeIdErr = function(data){

    var correctKey = "0000";
    var key = "#userId";

    var res = {};

    if(data != null){
        res = $scope.handleError(data, idIn, correctKey, key, $scope.errors);
        $scope.errors = res[0];
        idIn = res[1];
    }

};

reads this value (res[0]) and stores it in $scope.errors which ultimately is iterated over on the next input event by:

function theIndexOf(val){
    console.log("find index in array of length:  " + errorsDescription.length)
    for(var i = 0; i < errorsDescription.length; i++){
        if(errorsDescription[i].selector === val){
            return i;
        }
    }
}

due to your factory returning that object when asked for errors. To fix this, you should keep a static list that you never remove from which provides the error definitions. This is what you should refer to when you push to errorArray in your first code block.

Comments