AngularJS与$ resource和自定义格式化程序/解析器指令无法正常工作

时间:2013-09-12 23:08:53

标签: angularjs

以下是一个例子:

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更改为指向“data”对象的字段,它将按预期工作。

2 个答案:

答案 0 :(得分:0)

我遇到了同样的问题并找到了fix(至少是最新的Angular)。

正如Glav所述,ngModel观察者未被触发。这是because Angular's modelWatch is just checking for object identity。为了防止这种情况,我复制了(稍微修改过)之后出现的来源。现在我们有一个新的directive,我们可以插入ngModels $resource。我可能会更新这个,以便有一个可配置的&#34;待定&#34;消息/指令(以及正确的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;
            });
        }
    };
});

编辑:我的答案是module。你可以像bower一样使用它:

bower install https://github.com/P-Seebauer/ng-isFutureModel.git

答案 1 :(得分:-2)

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

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

无论出于何种原因,当$ resource将调用的结果分配给作用域上的'data'时,不会触发监视,因此当$ resource完成时,textarea的模型不会更新,所以最初$ scope.data是text和{}显示在文本区域,进行$ resource调用,$ scope.data更新,但是textarea watch没有启动。使用$ http服务并手动将调用结果分配给$ scope.data确实有效,并触发相应的$ watch。

你可以通过添加

来看到这一点
$scope.$watch('data',function() {....}); 

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