0

I am trying to read a file in angular js where if the data is read successfully it will assign the content to a variable of an object else it will assign "NA" to that same variable.

function customer($scope, $http) {
    var i;
    $scope.courses = [{
        name: "CSE",
        capacity: "CSE.txt"
    }, {
        name: "IT",
        capacity: "IT.txt"
    }, {
        name: "ECE",
        capacity: "ECE.txt"
    }];

    for (i = 0; i < 3; i++)
        $http.get($scope.courses[i].capacity).then(function (success) {
            $scope.courses[i].capacity = success.data;
        }, function (error) {
            $scope.courses[i].capacity = "NA";
        });

}

var myApp = angular.module("myApp", []);
myApp.controller("customerobj", customer);

I try to access the following part in a normal table format

<td>ng-repeat="course in courses">{{course.capacity}}</td>

But every time I do that it's throwing an error: "Cannot set property 'capacity' of undefined" and showing the file names. Even though if the files are not found it is supposed to update the value to "NA". But it is not happening. Please help me out

Darshak
  • 859
  • 7
  • 18

4 Answers4

2

Wrap your http service call in another function like below and call that function in loop so that loop index i value will persist in function scope.

Update:

If you don't want a separate function you can use anonymous functions also

Solution 1

for (i = 0; i < 3; i++) {
    (function (index) {
        $http.get($scope.courses[index].capacity).then(function (success) {
            $scope.courses[index].capacity = success.data;
        }, function (error) {
            $scope.courses[index].capacity = "NA";
        });
    } (i))
}

Solution 2

for (i = 0; i < 3; i++) {
  serviceCall(i)
}

function serviceCall(index) {
  $http.get($scope.courses[index].capacity).then(function (success) {
    $scope.courses[index].capacity = success.data;
  }, function (error) {
    $scope.courses[index].capacity = "NA";
  });
}
Gangadhar Jannu
  • 4,136
  • 6
  • 29
  • 49
  • It is working. Sir, if you don't mind, can you plz explain it a little bit? – Siddhartha Choudhury Feb 16 '17 at 05:55
  • @SiddharthaChoudhury It is called as **closure**. *If you put the function outside of the loop, each index variable is bound to the function otherwise they will share the same variable*. I would recommend to have a look on [closure inside loops](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Gangadhar Jannu Feb 16 '17 at 06:10
  • That's the solution of the duplicate. You should instead have voted to close this one as a dupe... – Andreas Feb 16 '17 at 07:06
  • @Andreas Though the underlying concept is similar, OP was unable to understand the context even after we both commented. Then only I had given answer. – Gangadhar Jannu Feb 16 '17 at 08:00
1

Use let in for loop

for (let i = 0; i < 3; i++) { 
...... 
}

Ref:

http://caniuse.com/#search=let https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/let

Prasanth Bendra
  • 31,145
  • 9
  • 53
  • 73
0

code is corret. but for loop is not. when you add console.log(i) to error function you see 3. but your array has 3 member. http request is async. for loop can not wait its response. use Gangadhar Jannu solution.

seyfside
  • 117
  • 1
  • 7
0

I think using let in for loop is the much better approach to handle this type of cases. Let in the loop can re-binds it to each iteration of the loop, making sure to reassign it the value from the end of the previous loop iteration, so it can be used to avoid issue with closures

for (let i = 0; i<3;i++) {

}

everytime when async code inside for loop will be executed it will get correct value of i

nishant agrawal
  • 471
  • 2
  • 7