以下是解释:
我有当前的控制器,它创建了一个$ 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 ......但没有运气。
我已经创建了一个“侦探”来重现我现有的内容:
到目前为止,我可以创建和删除数组中的对象,但是我无法获得单个对象来根据$ index更新控制器的对象。
如果解释不清楚,请务必告诉我,我会详细说明。
谢谢
答案 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 强>