为什么我无法从控制器中查看服务的属性?

时间:2015-10-05 03:36:02

标签: javascript angularjs angularjs-scope

现场代码:Here

我已将一个名为FileTraversal的服务添加到模块divkick.services中。我还有一个模块divkick.container,其控制器名为ContainerCtrl

我已在ContainerCtrl中添加了一个观察程序功能,并希望能够观看FileTraversal.stuff数组。

问题:我觉得这是一个愚蠢的语法问题,如何从ContrainerCtrl

中观看FileTraversal.stuff

主要应用程序:

(function () {
  "use strict";
  angular.module('divkick', [
    'divkick.services',
    'divkick.components',
    'divkick.container'
  ]);
})();

控制器:

(function () {
  angular
      .module('divkick.container', [])
      .controller('ContainerCtrl', ContainerCtrl)

  ContainerCtrl.$inject = ['FileTraversal', '$scope', '$timeout'];
  /* @ngInject */
  function ContainerCtrl(FileTraversal, $scope, $timeout) {
    /* jshint validthis: true */
    var main = this;

    activate();

    ////////////////

    function activate() {
      $scope.$watch(
          // This function returns the value being watched. It is called for each turn of the $digest loop
          function() { return FileTraversal.stuff; },
          // This is the change listener, called when the value returned from the above function changes (but not working) :(
          function(newValue, oldValue) {
            if ( newValue !== oldValue ) {

              console.log(newValue);
            } else {
              console.log('nope');
            }
          }
      );
    }
  }
})();

服务:

(function () {
  "use strict";
  var fs = require('fs');
  var glob = require("glob");
  angular
      .module('divkick.services', [])
      .factory('FileTraversal', FileTraversal);


  /* @ngInject */
  function FileTraversal() {
    var service = {
      stuff: [],
      check: check
    };

    return service;

    ////////////////

    function check(filePath) {
      glob(filePath + '/**/*{.png,.jpg,.gif}', function (er, files) {
        if(er) return er;
        service.stuff = files;
      });
    }
  }
})();

我尝试过像这样的集合:

$scope.$watchCollection(

          function() { return FileTraversal.stuff; },
          function(newValue, oldValue) {
            if ( newValue !== oldValue ) {
              // Only increment the counter if the value changed
              console.log(newValue);
            } else {
              console.log('nope');
            }
          }
      );

2 个答案:

答案 0 :(得分:1)

尝试观看集合而不是观看

$scope.$watchCollection(function () {
    return FileTraversal.stuff;
}, function (newValue, oldValue) {
    console.log("check")
    if (newValue !== oldValue) {

        console.log(newValue);
    } else {
        console.log('nope');
    }
});

N:B:

你没有在小提琴视图中添加ng-controller。可能这是一个错字

JSFIDDLE

答案 1 :(得分:0)

问题是您使用的是$watch而不是$watchCollection

$watch目前正在查看指向数组的属性。即使数组发生更改,指向数组的属性也不会更改 - 指针是相同的。所以$watch没有检测到这一点。

如果您使用$watchCollection,angular将知道检查集合以查看集合中的任何元素是否已更改。

有关详细信息,请参阅The Three Watch Depths of AngularJS

Plunker Demo

angular
  .module('app', [])
  .controller('MainController', MainController)
  .factory('Factory', Factory)
;

function MainController(Factory, $scope) {
  var main = this;
  main.factory = Factory;
  main.addToArray = function() {
    main.factory.array.push('added');
  };
  
  // watching primitive
  $scope.$watch(function() {
    return Factory.primitive;
  }, function(newVal, oldVal) {
    if (newVal === oldVal) {
      console.log('primitive unchanged');
    }
    else {
      console.log('primitive changed');
    }
  });
  
  // watching array
  $scope.$watchCollection(function() {
    return Factory.array;
  }, function(newVal, oldVal) {
    if (newVal === oldVal) {
      console.log('array unchanged');
    }
    else {
      console.log('array changed');
    }
  });
}

function Factory() {
  return {
    primitive: 'foo',
    array: []
  };
}
<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script data-require="angular.js@1.4.6" data-semver="1.4.6" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <div ng-controller="MainController as main">
      <input ng-model="main.factory.primitive" />
      <button ng-click='main.addToArray()'>Add to array</button>
    </div>
  </body>

</html>