当共享控制器对象发生更改时,使多个指令保持最新

时间:2015-11-27 17:03:25

标签: angularjs

我有三个指令都使用一个控制器。用户可以进入并编辑其名称,该名称调用服务以在后端更新其详细信息。然后应该使用返回的数据来填充在promises解析中使用它的其他指令。

我遇到的一个问题是,当查看其中一个指令时,我必须重新加载页面才能看到更改填充。我的解决方案是在$ rootScope上使用$ broadcast并使用需要它的指令来监听,但这看起来有点过分,我不想依赖于此,因为最终会出现性能损失:

(function() {
  'use strict';

  angular
    .module('flowlens')
    .directive('flUserCard', flUserCard);

    function flUserCard() {

        var directive = {
           restrict: 'E',
           controller: FlUserController,
           controllerAs: 'vm',
           scope: {},
           bindToController: {
              user: '=',
              userId: '@',
              size: '@'
           },
           templateUrl: '/templates/fl-users/fl-user-card.html',
           link: function(scope, elem, attrs, ctrl){
              if(scope.vm.size == "small"){
                scope.vm.cardClasses = "col-xs-12 col-lg-4";
                scope.vm.lineClasses = "col-xs-12";
                scope.vm.hrClasses    = "";
              } else {
                scope.vm.cardClasses  = "col-xs-12";
                scope.vm.lineClasses  = "col-xs-12 col-lg-4";
                scope.vm.hrClasses    = "hidden-lg-up";
              }
           }
        };
        return directive;
   }

  angular
    .module('flowlens')
    .directive('flUserShow', flUserShow);
  function flUserShow() {

    var directive = {
      restrict: 'E',
      controller: FlUserController,
      controllerAs: 'vm',
      scope: {},
      bindToController: {
        user: '=',
        userId: '@',
      },
      templateUrl: '/templates/fl-users/fl-user-show.html',
      link: link
    };

    function link(scope, ele, attrs, vm) {
      scope.$on('name change', function(evt,data) {
        vm.user = data.user;
      });
    }

    return directive;
  }

  angular
    .module('flowlens')
    .directive('flUserEdit', flUserEdit);
   function flUserEdit() {
    var directive = {
      restrict: 'E',
      controller: FlUserController,
      controllerAs: 'vm',
      scope: {},
      bindToController: {
        user: '=',
        userId: '@',
      },
      templateUrl: '/templates/fl-users/fl-user-edit.html'
    };

    return directive;
   }

  FlUserController.$inject = ['FlUsersService', '$state',   '$rootScope'];

  function FlUserController(FlUsersService, $state, $rootScope){
    var vm = this;
    vm.update = update;

    activate();

    function activate(){
       if( !vm.user ) {
             FlUsersService.get({id: vm.userId}, function(result){
             vm.user = result.contact;
          }, function(result){
             console.log(result);
          });
       }
    }

    function update(){
      FlUsersService.update({id: vm.userId, contact: vm.user},     function success(result){
         angular.merge(vm.user, result.user);
         $rootScope.$broadcast('name change',{user: vm.user});
         $state.go('users.show', {userId: vm.user.id});
      }, function failure(result){});
    }
  }
 })();

所以我的问题就是这个 - 是否有更有效的方法来做同样的事情以确保在控制器更新用户对象时更新所有指令?

由于

修改

这就是我将它们传递给指令的方式 - 双重绑定:

var directive = {
  restrict: 'E',
  controller: FlUserController,
  controllerAs: 'vm',
  scope: {},
  bindToController: {
    user: '=',
    userId: '@',
    size: '@'
  },
  templateUrl: '/templates/fl-users/fl-user-card.html',
  link: function(scope, elem, attrs, ctrl){
       if(scope.vm.size == "small"){
         scope.vm.cardClasses = "col-xs-12 col-lg-4";
         scope.vm.lineClasses = "col-xs-12";
         scope.vm.hrClasses    = "";
       } else {
         scope.vm.cardClasses  = "col-xs-12";
         scope.vm.lineClasses  = "col-xs-12 col-lg-4";
         scope.vm.hrClasses    = "hidden-lg-up";
       }
     }
  };
 return directive;

所有指令都有相同的签名减去链接部分

1 个答案:

答案 0 :(得分:1)

我建议为这个“全球”对象介绍服务。您可以将此服务作为依赖项并放入范围(如果需要)。您可以将value用作简单的对象存储空间(value是最简单的Provider)。

通过这种方式,您可以抽象修改源 - 您不关心修改对象的人,只需跟踪更改。

var app = angular.module('test', []);
app.value('user', {});
app.directive('first', function() {
  return {
    restrict: 'E',
    template: '<div>First directive, name={{ctrl.user.name}}</div>',
    controller: CommonCtrl,
    controllerAs: 'ctrl'
  }
});
app.directive('second', function() {
  return {
    restrict: 'E',
    template: '<div>Second directive, name={{ctrl.user.name}}</div>',
    controller: CommonCtrl,
    controllerAs: 'ctrl'
  }
});

function CommonCtrl($scope, $timeout, user) {
  if (!user.loaded) {
    $timeout(function() {
      if (!user.loaded) {
        user.name = 'Bob';
        user.loaded = true;
      }
    }, Math.random() * 500);
  }
  this.user = user;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test">Loading...
  <first></first>
  <second></second>
</div>

我假设你有“全球”对象。如果你有“范围”,你可以拥有多个对象,但在某个层次结构中共享,你可以引入一些“对象持有者”指令,并在所有可以使用它的指令中要求它。

注意:您可以更改对象的属性,但不能更改对象本身。您可以使用angular.extend将属性从后端对象放入存储对象,或使用注入对象的单个属性(例如user.value = valueFromBackend