user4097807
user4097807

Reputation:

JavaScript array.push (object) with Angular ng-repeat not functioning as expected

I have almost the exact same snippet of code in other areas of my application and it works perfectly fine.

I'm pushing an object into an empty array and have an ng-repeat in my view.

JavaScript:

$scope.upload = $upload.upload({
    url: BASE + 'files/tasks',
    file: file,
    data: data
}).success(function(data) {
    for(var i = 0; i < $scope.case.task.notes.length; i++) {
        if($scope.case.task.notes[i].in_api === false) {
            $scope.case.task.notes[i].documents.push(data);
        }
    }
});

When I console.log the $scope.case.task.notes after adding the JSON response to the array, I see the expected result (the note object along with the documents array, with the returned object in the documents array).

In my view, the page has the HTML below augmented with Angular templating:

<div>
    <p class="chat-file row" ng-repeat="document in note.documents track by $index">
        <b class="pull-left col-sm-6">
            <i class="fa fa-file"></i> {{document.name}} 
        </b>
        <span class="col-sm-6 pull-right"> 
            <a href="http:/download.com?f={{document.id}}&n={{document.name}}" class="btn btn-xs btn-success">download</a> 
        </span>
    </p>
</div>

When I first load the page, all of the notes that do have documents show up correctly. However, when the success function is called from the above upload function, and the document is pushed onto the note's array, it does not appear in the view.

If it makes a difference, the HTML above is also surrounded inside of an ng-repeat that iterates over every note (so it's multi-level).

What could be the problem? The JavaScript function is functioning appropriately but the view is not updating when the model does.

Upvotes: 1

Views: 1491

Answers (2)

Brent Washburne
Brent Washburne

Reputation: 13138

You seem to be using different variables. In the HTML, you use note.documents:

ng-repeat="document in note.documents ...

In the JavaScript, you use $scope.case.task.notes[i].documents.

You need to make them reference the same array. Maybe if you set

$scope.documents = $scope.case.task.notes[i].documents;

in your JavaScript and change the HTML to read

ng-repeat="document in documents ..."

then Angular with pick up the changes?

Upvotes: 0

nanndoj
nanndoj

Reputation: 6770

Try to use $scope.$apply() to tell your view that scope data has changed:

 .success(function(data) {
     // Do what you want.
     $scope.$apply();
 });

$apply() is used to execute an expression in angular from outside of the angular framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). Because we are calling into the angular framework we need to perform proper scope life-cycle of exception handling, executing watches.

Upvotes: 4

Related Questions