1

这是一个例子:

http://plnkr.co/edit/ezTUdoDKhCUGX3848VLp

HTML:

<p>Hello {{data | json}}!</p>

<div>
  <textarea myconverter ng-model="data"></textarea>
</div>

JavaScript:

var app = angular.module('plunker', ['ngResource']);

app.controller('MainCtrl', function($scope, $resource) {
  $scope.data = $resource('some-data.json').get({});
})
.directive('myconverter', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attr, ngModel) {

            function fromJson(json) {
                var out = JSON.stringify(json, null, 2);
                return out;
            }

            function toJson(text) {
                return JSON.parse(text);
            }
            ngModel.$parsers.push(toJson);
            ngModel.$formatters.push(fromJson);
        }
    };
})
;

简单的 Hello 部分工作正常,当 AJAX 调用返回时,它会使用正确的数据进行更新。但是 textarea 永远不会更新。如果我设置了一个断点,它似乎被赋予了一个没有数据的对象(但我可以看到 $resource 方法)。如果我将 textarea 更改为指向“数据”对象的字段,它会按预期工作。

4

2 回答 2

0

我遇到了同样的问题并找到了解决方法(至少对于最新的 Angular)]。

正如Glav正确提到的,ngModel观察者不会被触发。这是因为 Angular 的 modelWatch 只是检查对象身份。为了防止这种情况,我复制(并稍微修改)了后来的源代码。现在我们有一个新directive的,我们可以插入ngModels它有一个$resource. 稍后我可能会更新它,以获得可配置的“待处理”消息/指令(以及正确的priority设置)。

app.directive('isResourceModel', function() {
  return {
  restrict: 'A',
  require: 'ngModel',

  link: function(scope, element, attr, ctrl) {
            ctrl.$formatters.push(function resourceFormatter(value){
              if (value.$promise != null && value.$resolved === false){
                value.$promise.then(function (data){
                  var viewValue = data, 
                    idx = ctrl.$formatters.length,
                    runFormatter = false;

                  while(idx--){
                    formatter = ctrl.$formatters[idx];
                    if (runFormatter
                        || (runFormatter = formatter === resourceFormatter))
                        viewValue = formatter(viewValue)
                  }
                  ctrl.$viewValue = viewValue;
                  ctrl.$render();
                  if (ctrl.$validators.length > 0)
                    ctrl.$validate();
                  });  
              }
              return value;
            });
        }
    };
});

编辑:我从答案中制作了一个模块。你可以像这样使用它bower

bower install https://github.com/P-Seebauer/ng-isFutureModel.git
于 2014-11-09T17:40:48.970 回答
-2

该问题与您的指令无关。在您的控制器中,将 $resource 的使用替换为使用这样的 $http 服务的东西(显然在您的控制器依赖项中包含 $http ):

$scope.data = $http({
    url:'some-data.json',
    method:"GET"
  }).then(function(result) {
    $scope.data = result.data;  
  });

无论出于何种原因,当 $resource 将调用结果分配给范围上的“data”时,不会触发任何监视,因此当 $resource 完成时,textarea 的模型不会更新,因此最初 $scope.data 为空并且 { } 显示在文本区域中,进行了 $resource 调用,并更新了 $scope.data,但是 textarea watch 没有启动。使用 $http 服务并手动将调用结果分配给 $scope.data确实有效并触发了适当的 $watch 。

您可以通过添加看到这一点

$scope.$watch('data',function() {....}); 

在你的控制器中的某个地方,当使用 $resource 时,你会看到手表最初只调用一次。当 $resource 调用完成时,$watch 永远不会被触发。

于 2013-09-13T00:45:32.437 回答