0

I have this html code :

<table class="table table-striped table-condensed table-hover">
    <tbody>
        <tr ng-repeat="doc in container.Documents ">
                {{doc.Status.Message}}
            </td>
            <!-- .... -->
        </tr>
    </tbody>
</table

and this angularjs controller:

(function (ng, app) {

    "use strict";

    app.controller(
        "my.DocumentsController",
        function ( $scope, $stateParams, MYContainer, $timeout ) {

            $scope.container = new MYContainer();            
            $scope.$watch('container', function (newVal, oldVal) {
                $timeout(function () {
                    $scope.$apply();
                }, 0);
            }, true);

            $scope.container.load($stateParams.Id);
    });
})(angular, my_app);

the load function of MYContainer:

function load(id) {
    var scope = this;
    var deffered = $q.defer();
    containerService.getData(id, "true").success(function (data) {
        angular.extend(this, data);
        deffered.resolve();
    }).error(function (e) {
        deffered.reject('Error while loading container');
    });
    return deffered.promise;
}

The problem is that whenever I reload the batch (with modified container.Documents) it does not show the modified batch in the html view.

I've read about equality watches in angular so I added the watch function in the controller, and it does detect the modification in the watch function so I call $scope.$apply() but it does not change in html.

If I put 200 ms in the $timeout call instead of 0 the view gets changed.

2 Answers 2

3

You don't need to use any watchers or $apply here, angular is capable of taking care of this and updating the view when the data changes. Moreover, $watchers are expensive performance-wise, and $scope.$apply is something that is recommended to avoid unless absolutely necessary, which is not here.

$angular.extend is not a deep copy. You can read about it here.

I suggest you change your code to this:

load($stateParams.Id).then(function(result) {
    $scope.container = result;
});

And removing angular.extend(this, data); from the success callback.

Also remove the entire $watch section, it's redundant.

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

4 Comments

the load function is not in the controller, it is in MYContainer object
So I can call (new MYContainer()).load(id); in my controller
@A.K That's ok, call it however you need. The rest is what matters.
I've used angular.copy() instead of angular.extend() and it did the job.
1

It's pointless to call $timeout(0) or $apply inside a $watch, as the $watch itself is called by a digest - and the point of calling $apply would be triggering a digest.

Rather, you want to force this digest when the data is changed asynchronously - in this case, when the load promise is resolved.

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.