AngularJS:如何更改与指令范围对象关联的控制器范围?

时间:2015-01-27 03:34:53

标签: javascript angularjs angularjs-directive angularjs-scope angularjs-ng-repeat

以下是解释:

我有当前的控制器,它创建了一个$ scope.plan.steps数组,用于存储每一步:

.controller('PlanCtrl', function ($scope, $http) {
    $scope.plan = {
        steps: [{}]
    };

    $scope.addStep = function () {
        $scope.tutorial.steps.push({});
    }
}

然后我有以下指令,该指令具有隔离范围并且与$ scope.plan.steps数组的索引相关联:

.directive('planStep', function () {
    return {
        template: '<input type="text" ng-model="step.name" />{{step}}',
        restrict: 'E',
        scope: {
            index: '=index'
        },
        transclude: true,
        controller: function($scope, $element, $transclude) {

            $scope.removeStep = function() {
                $scope.$emit('removeStep', $scope.index);
                $element.remove();
                $scope.$destroy();
            }

        }
    };
});

这两个通信,创建和删除控制器范围内的对象,但是,如何允许指令实时更新控制器的范围数组?

我已尝试对指令的隔离范围更改进行$ watch,$发出对控制器的更改,并指定$ index ......但没有运气。

我已经创建了一个“侦探”来重现我现有的内容:

Link

到目前为止,我可以创建和删除数组中的对象,但是我无法获得单个对象来根据$ index更新控制器的对象。

如果解释不清楚,请务必告诉我,我会详细说明。

谢谢

2 个答案:

答案 0 :(得分:3)

当您在ng-repeat内执行此类操作时,您可以利用ng-repeat创建的子范围并在没有隔离范围的情况下工作。

这里是相同的指令而不需要任何角度事件

.directive('planStep', function() {
    return {
      template: '<button  ng-click="removeStep(step)">Delete step</button><br><input type="text" ng-model="step.name" />{{step}}<br><br>',
      restrict: 'E',          
      transclude: true,
      controller: function($scope, $element, $transclude) {
       var steps =  $scope.plan.steps// in scope from main controller
        /* can do the splicing here if we want*/
        $scope.removeStep = function(step) {
          var idx =steps.indexOf(step) 
           steps.splice(idx, 1);
        }
      }
    };
  });

另请注意,使用element.remove()删除元素是多余的,因为当数组拼接时,它会自动被角度删除

至于更新,它会实时更新项目

DEMO

答案 1 :(得分:1)

您为索引设置双向绑定的方式也可以为step设置一个?并且你真的不需要索引来删除项目,尽管你的指令是孤立的,但它依赖于ng-repeat的索引,这可能不是一个好主意。

<plan-step ng-repeat="step in plan.steps" index="$index" step="step"></plan-step>

并在你的指令中:

scope: {
    index: '=index',
    step:'='
 },

<强> Demo

删除$ index依赖项和冗余元素remove()和范围destroy(当从数组中删除项目时,将自行管理它):

 return {
  template: '<button  ng-click="removeStep()">Delete step</button><br><input type="text" ng-model="step.name" />{{step}}<br><br>',
  restrict: 'E',
  scope: {
    step:'='
  },
  transclude: true,
  controller: function($scope, $element, $transclude) {
    $scope.removeStep = function() {
      $scope.$emit('removeStep', $scope.step);
    }
  }

并在您的控制器中:

 $scope.$on('removeStep', function(event, data) {
  var steps = $scope.plan.steps;
  steps.splice(steps.indexOf(data), 1);
});

<强> Demo

如果你想摆脱$ emit,你甚至可以使用带有函数绑定(&amp;)的隔离范围指令来公开api。

return {
  template: '<button  ng-click="onDelete({step:step})">Delete step</button><br><input type="text" ng-model="step.name" />{{step}}<br><br>',
  restrict: 'E',
  scope: {
    step:'=',
    onDelete:'&' //Set up function binding
  },
  transclude: true
};

并在视图上注册:

<plan-step ng-repeat="step in plan.steps"  step="step" on-delete="removeStep(step)"></plan-step>

<强> Demo