0

I have a directive and i am trying to watch one of scope's members, an array of objects.

        <div ng-repeat="image in images track by $index" class="cr-form image-block-holder clearfix">
            <div ng-class="images[$index].imageFile == undefined ? 'image-upload' : 'image-upload image-active'">
                <div class="cr-file-upload" style="position: relative">
                    <input id="crChooseFile" type="file" ngf-select ng-model="images[$index].imageFile" ngf-multiple="false" ng-attr-accept="image/*" 
                           class="form-control ng-pristine ng-invalid ng-invalid-required ng-touched" name="uploadField" image="imageFile" />

                </div>
                <div class="cr-edit-business-profile">
                    <div class="cr-business-logo">
                        <img class="cr-profile-logo-img" ng-show="images[$index].imageFile" ng-src="{{images[$index].imageFile.url}}" type="{{images[$index].imageFile.file.type}}" />
                        <img ng-show="images[$index].imageFile == null && images[$index].logo" ng-src="{{images[$index].logo}}" type="image/png" />
                    </div>
                </div>
                <div class="image-label">
                    <label>Browse</label> <br />
                </div>
            </div>

            <div class="form-elements">
                <div class="input-inner">
                    <textarea type="text" ng-model="images[$index].caption" ng-keyup="setCaption($index)" placeholder="Add Caption"></textarea>
                </div>
            </div>
        </div>

And this is the watch in my directive:

                scope.$watch(function () { return scope.images }, function (newValue, oldValue) {
                    if (newValue && oldValue) {
                        $timeout(function () {
                            var changedIndex = -1;
                            for (var i = 0; i < scope.content.noOfImages && changedIndex == -1; i++) {
                                if (isDifferentImage(newValue[i].imageFile, oldValue[i].imageFile))
                                    changedIndex = i;
                            }
                            if (changedIndex == -1)
                                return;
                            scope.content.images[changedIndex].photo = newValue[changedIndex].imageFile;

                        }, 0, false);
                    }
                }, true);

I also tried with watchCollection, it does not get fired, without deep watch it does not get fired either. ng-change event does not seem to do the trick; deep $watch on objects array is returning Illegal invocation.

Any idea how to make this work? I am using angular 1.4.5

4
  • Can you post a plunker or example? Commented Jan 9, 2017 at 16:25
  • When asking a question about a problem caused by your code, you will get much better answers if you provide code people can use to reproduce the problem. That code should be Minimal, Complete, and Verifiable. Commented Jan 9, 2017 at 16:43
  • $watch only works well with JavaScript objects, arrays, strings, and primitives. When the contents includes special objects such as DOM elements, blobs, files, events, etc., it gets problematic Commented Jan 9, 2017 at 16:55
  • sorry, i'll keep that in mind next time, you are right, thanks for the remark! Commented Jan 10, 2017 at 8:56

1 Answer 1

3

This is because your images array contains File objects.

The following can be found in the $watch documentation:

This should not be used to watch for changes in objects that are or contain File objects due to limitations with angular.copy.

You will have to solve it another way.

For example watching an array of file names instead (or name + lastModified if name is not enough for your use case):

$scope.$watch(function() {
  return $scope.files.map(function(file) {
    return file && file.name;
  });
}, function() {

  // Code

}, true);

Have seen the following in use as well:

$scope.$watch(function() {
  return JSON.stringify($scope.files);
}, function() {

  // Code

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

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.