【问题标题】:Directive does not update on service model change指令未更新服务模型更改
【发布时间】:2014-12-09 10:20:36
【问题描述】:

我有一个包含我的应用程序模型的服务:

angular.module('adminClient').factory('myApi', function () {
    var model = {};
    model.myObject = {
        label: 'New York City'
    };

    return {
        model: function () {
            return model;
        }
    };
});

partial/controller 可以访问模型并且可以设置一个新的 myObject:

angular.module('adminClient').controller('MySelectNetworkCtrl', function ($scope, myApi) {

    $scope.myObject = myApi.model().myObject;

});

除此之外,我还有一个指令应该显示 myObject 中包含的标签:

angular.module('nav').directive('myTopBar', function(myApi) {
    return {
        restrict: 'E',
        replace: true,
        scope: {},
        templateUrl: 'nav/directive/my-top-bar/my-top-bar.html',
        link: function(scope, element, attrs, fn) {
            scope.myObject = myApi.model().myObject;
        }
    };
});

这是 HTML:

<div id="my-top-bar">
    <span ng-bind="myObject"></span>
</div>

当我运行应用程序时,标签显示正常(纽约市),但一旦控制器更改 myObject,指令中的标签保持不变。我也可以在 Chrome Angular 范围检查器中看到这一点。

知道如何让指令在被控制器更改后显示当前值吗?

【问题讨论】:

  • with a scope: {} 在指令中定义您正在创建新的隔离范围,尝试将其删除。
  • 我尝试将范围设置为 true,但这没有帮助。恕我直言,我需要一个孤立的范围,因为我正在使用包含所有数据的服务。

标签: angularjs angularjs-directive angularjs-service


【解决方案1】:

这完全取决于控制器如何更新模型对象。因为你的代码

scope.myObject = myApi.model().myObject;

获取这个特定的模型对象,只要模型对象myObject的属性发生变化,它就可以正常工作。

但是如果控制器这样做了

myApi.model().myObject= {}; //or any new object

现在服务返回的模型有不同的myObject,指令也不同。因此更改不起作用。

代替指令做:

scope.myObject = myApi.model(); // bind to model

并相应地更新指令模板中的绑定。看看有没有效果

【讨论】:

  • 我明白你在说什么。但是,这也不起作用。我现在添加了 $scope.$watch('model.myObject', function (newValue, oldValue) { $scope.$apply(); });它可以工作,但现在它也显示一个错误:[$rootScope:inprog] $digest 已经在进行中。把我逼疯了!
  • 我肯定与摘要周期没有更新模型有关,因为当我执行其他一些点击/操作时,值会在下一个摘要周期更新。不知道为什么它不更新服务中的模型。有什么想法吗?
  • 如果你的手表被触发了,你不需要在里面做 scope.$apply。
【解决方案2】:

查看plunkr

如果您想在控制器中修改myObject,并且还希望此更改反映在您的my-top-bar 指令中,然后从myApi 服务更新指令的范围,那么您应该这样做。

在您的控制器中更新myObject,然后通过setter 方法在您的服务中更新它。

// Doing this will update your scope.myObject but 
// will not change the moObject in your service
$scope.myObject = {
  label: 'updated label'
};

// This will update your service, and anyone making a myApi.myApi.model() after this will get an updated myObject
myApi.setModel($scope.myObject);
// Notify directive of the change
$scope.$broadcast('updateDirective');

在工厂里:

angular.module('plunker').factory('myApi', function() {
  var model = {};
  model.myObject = {
    label: 'New York City'
  };

  return {
    model: function() {
      return model;
    },
    setModel: function(newModel) {
      model.myObject = newModel;
    }
  };
});

最后是指令:

angular.module('plunker').directive('myTopBar', function(myApi) {
  return {
    restrict: 'E',
    replace: true,
    scope: {},
    templateUrl: 'top-bar.html',
    link: function(scope, element, attrs, fn) {
      console.log('in directive link', myApi.model().myObject);
      scope.myObject = myApi.model().myObject;
    },
    controller: function($scope) {
      $scope.$on('updateDirective', function() {
        console.log('updating the scope of directive so that ng-bind works');
        $scope.$apply(function() {
          $scope.myObject = myApi.model().myObject;
          console.log($scope.myObject);
        });
      });
    }
  };
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    • 2018-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-02
    • 1970-01-01
    相关资源
    最近更新 更多