AngularJS:如何在指令作用域的对象发生变化时更新关联的控制器作用域?

AngularJS : How to update controller scope associated to directive scope's object as it changes?

解释如下:

我有当前控制器创建一个 $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,将更改 $emit 到控制器,并指定 $index...但没有成功。

我创建了一个 plunker 来重现我目前拥有的内容:

Link

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

如果解释不清楚,一定要告诉我,我会详细说明。

谢谢

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

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

并在您的指令中:

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

Demo

去除$index依赖和冗余元素remove()和scope destroy(当元素从数组中移除时angular会自行管理):

 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,您甚至可以使用带有函数绑定 (&) 的独立作用域指令公开一个 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

当你在 ng-repeat 中做这样的事情时,你可以利用 ng-repeat 创建的子作用域并在没有隔离作用域的情况下工作。

这是相同的指令,不需要任何 angular 事件

.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() 删除元素是多余的,因为它会在拼接数组时被 angular 自动删除

关于更新,会实时更新商品

DEMO