如何在控制器中修改指令隔离范围变量,同时仍保持隔离状态?

时间:2017-08-01 20:10:33

标签: javascript angularjs angularjs-directive angularjs-scope

我有一个带有隔离范围的指令。我正在修改从指令控制器中的父控制器传递的一个变量。我遇到的问题是,当我在同一视图上使用此指令的多个实例(具有不同的optionsmodel)时,options对象不会保持唯一指令的实例。相反,它成为共享变量,指令的所有实例都使用相同的options对象。

因此,如果我在我的视图中使用过它们,请使用optionsA.isFlagOn = trueoptionsB.isFlagOn = false

<my-directive model="modelA" options="optionsA">
<my-directive model="modelB" options="optionsB">

modelB的{​​{1}}指令加载optionsA

如何为每个特定实例修改options时保持唯一性?

angular.module('myModule', [])
.directive('myDirective', function($compile) {
  template = '<h3><span ng-bind="model.title"><h3><p><span ng-bind="options"></span></p>';
  return {
    restrict: 'AE',
    scope: {
       model: "=",
       options: "=?" //A JSON object
    },
    controller: function($scope) {
      $scope.options = $scope.options || {};
      //A function that sets default values if no options object passed
      ensureDefaultOptions($scope);

      //now based on some of the options passed in, I modify a property in the options object
      if ($scope.options.isFlagOn)
        $scope.options.thisProp = true;
    },
    link: function(scope, element, attr) {
      let content = $compile(template)(scope);
      element.append(content);
    }
  };
}

编辑:我解决了我的问题。我的解决方案发布在下面的答案中。

3 个答案:

答案 0 :(得分:0)

您可以将其更改为单向绑定:

scope: {
       model: "=",
       options: "<?" //A JSON object
    }

答案 1 :(得分:0)

您的指令应该复制传入的选项并结合默认值,因此每个指令实例都有自己的选项对象。

您可以使用extend

轻松实现这一目标
var defaultOptions = { a:1, b:2, c:3 };
var options = angular.extend(defaultOption, $scope.options);
// then use options everywhere

请注意,这只会在初始化期间执行一次,因此如果您的选项是异步来自控制器,则需要额外处理。

答案 2 :(得分:0)

我使用1.4x或更高版本中可用的Angular指令的bindToController属性解决了它。

angular.module('myModule', [])
  .directive('myDirective', function($compile) {
    template = '<h3><span ng-bind="vm.model.title"><h3><p><span ng-bind="myOptions"></span></p>';
    return {
      restrict: 'AE',
      bindToController: {
        model: "=",
        options: "=?" //A JSON object
      },
      scope: {},
      controller: function() {
        var vm = this;

        //a function that handles modifying options
        vm.setOptions = function(options){
          let newOptions = {};
          angular.copy(options, newOptions);

          // modify newOptions here

          return newOptions;
        }

      },
      controllerAs: 'vm',
      link: function(scope, element, attr) {

         ensureDefaultOptions(scope.vm);

         scope.myOptions = scope.vm.setOptions(scope.vm.options);

         let content = $compile(template)(scope);
         element.append(content);
      }
    };
  });