2

I have a ng-repeat loop for a number of values. While looping, I fetch a variable from another array of values and use that:

<div ng-repeat="i in [1,2,3]">
    <div ng-init="obj = getObject(i)">
        <pre>{{ obj }} </pre>
    </div>
</div>

My goal is now to change a property of that variable and do a POST request containing the updated variable. The response for that from the server then contains all values, which I bind to $scope in order to update the view.

<a ng-click="change(obj, 5)">Set property to 5</a>

$scope.change = function(o, value) {
    o.prop = value;
    // save() sends a POST requests and returns a JSON with all values
    $scope.values = save(o);
}

This works, but only the first time I do it. All other changes will be reflected in the $scope.variables, but not in the {{ obj }} variables in the template. $scope.$apply() has no effect, either.

I've created a JS Fiddle to show my problem, which only mocks the HTTP requests. However, I have found that even when I run this code against my REST backend, the first time everything works fine but every time after that reflects no changes at all.

2
  • Your code is confusing to me. Why are you posting to the server on each iteration of a for loop, and binding the view to its response each time? I also don't understand what the purpose of getObject() is. Commented Oct 28, 2014 at 19:22
  • The example is simplified, but let me explain: getObject retrieves an object from another array based on the current $index (and other values not included in the example). Bear with me and ignore the POST request, you can see that it has no effect here: jsfiddle.net/0ps2d7Lp/7. Commented Oct 28, 2014 at 19:25

3 Answers 3

2

I think the issue is caused because you are using ng-init, which probably sets a non-changing value since you are calling a function. It will work once you change {{ obj }} to {{ getObject(i) }}. The only issue is that your variables are also being referenced and modified in the script allTwo and allThree are being modified since you directly assign them. I fixed that by cloning the objects, but it will probably not be an issue when you are using AJAX. Here is an updated version of your fiddle: http://jsfiddle.net/0ps2d7Lp/6/

Sign up to request clarification or add additional context in comments.

1 Comment

You are perfectly right, changing all occurences from {{ obj }} to {{ getObject(i) }} solved my problem. Thank you so much!!
2

I have made changes to your fiddle.

<div ng-repeat="i in [1,2,3]">
   <div>
     <pre>{{ getObject(i) }} </pre>
   </div>
</div>

Controller changes:

$scope.changeType = function(ids, type) {
    angular.forEach($scope.objects, function(o) {
        if (ids.indexOf(o.id) > -1) {
            o.type = type;   
            var response = (type === 2) ? allTwo : allThree

            $scope.objects = angular.copy(response);
        }
    });
};

Link to your updated fiddle is here

3 Comments

Good solution, but it might be helpful to explain why you made those changes
While this solution works with the JS fiddle I provided, the actual issue is the one mentioned in my reply to @Izzey's answer above.
I agree with @lzzey's explanation, thats the reason you need to remove ng-init, but you do not need to parse and stringify. JSON.parse(JSON.stringify(allTwo)) : JSON.parse(JSON.stringify(allThree)); Instead you can just use angular.copy() which will break the chain of referential data.
1

In your case, getObject() is necessary, but I excluded it in my answer for simplicity sake. I understand that you need to perform a PUT/POST request to update the objects on the server-side, but I don't believe it's necessary at all to re-bind the view to the server's response. Fundamentally, a PUT doesn't require a response other than 200 OK in most cases. The point is you're telling the server to update objects, not create them. Thus, no primary keys change, so, you don't need to rebind the objects. Changes are already resident in memory.

HTML

<div class="example" ng-controller="MyCtrl">       
    <div ng-repeat="obj in objects">
        <div><pre>{{ obj }}</pre></div>
    </div>
    <a href="#" ng-click="changeType([1,2,3], 2)">Change all to Type 2</a>
    <a href="#" ng-click="changeType([1,2,3], 3)">Change all to Type 3</a>
</div>

JavaScript

var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
    // initial objects
    $scope.objects = [
        { id: 1, type: 1 },
        { id: 2, type: 2 },
        { id: 3, type: 3 }
    ];

    $scope.changeType = function(ids, type) {
        angular.forEach($scope.objects, function(o) {
            if (ids.indexOf(o.id) > -1) {
                o.type = type;
                // Perform your PUT/POST request here for each
                // updated object to update it on the server-side.
                // There is no need to bind to a server response.
            }
        });
    };    
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.