我试图创建一个AngularJS指令来处理模态窗口,但我无法弄清楚如何隔离范围。我的目标是有一个模态窗口来添加新位置。我希望该指令使用父作用域中的任何所需数据填充模态并处理单击保存按钮。我使用父作用域工作了,但是我无法使用隔离范围。
父控制器有一个locations属性,在这种情况下是我需要的唯一父属性。 newLocation对象应与父作用域隔离。当我添加隔离范围时,不会填充名称输入,并且点击处理程序不会触发。范围声明仅允许@,=和&属性所以我不能在那里增加它,并且在链接中添加属性没有任何效果。
指令:
angular.module('pw').directive('addLocationModal', [
'appApi', function (appApi) {
return {
restrict: 'A',
scope: {
locations: '='
},
link: function (scope, element, attrs) {
scope.newLocation = {
name: 'xxx'
};
scope.saveLocation = function () {
alert('save location');
};
}
};
}
]);
模态:
<div class="modal fade" id="add-location-modal" add-location-modal>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span>×</span>
</button>
<h4 class="modal-title">Add Location</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" ng-model="newLocation.name" required />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" ng-click="saveLocation()">Save</button>
</div>
</div>
</div>
答案 0 :(得分:1)
你需要移动div
<div class="modal-dialog">...
指令的模板
return {
restrict: 'A',
templateUrl : 'view.html',
scope: {
locations: '='
},
link: function(scope, element, attrs) {
scope.newLocation = {
name: 'xxx'
};
scope.saveLocation = function() {
alert('save location');
};
}
};
view.html
中的
<div class="modal-dialog">
.....
.....
</div>
index.html
中的
<div class="modal fade" id="add-location-modal" add-location-modal>
</div>
directive
html应该针对指令范围进行编译(将范围数据和函数绑定到视图更可能绑定指令,如ng-click
,ng-model
这样的范围没有编译到期望的范围,它不会像我们预期的那样,在这里你没有指令模板,你假设html
中的指令div之间的index.html
表现为directive html
但它的实际上它不是。
将<div class="modal fade" id="add-location-modal" add-location-modal>
的内部内容移动到指令的模板将解决此问题。因为指令ng-model
和ng-click
是针对指令范围编译的,而不是它的父范围。
这是简单的DEMO
更新 - 第一条评论的解决方案
你可以在指令div之间编译html
并附加到指令compile
函数中的相同元素,
compile: function(tElement, tAttr, transclude) {
var contents = tElement.contents().remove();
var compiledContents;
return function(scope, iElement, iAttr) {
if (!compiledContents) {
compiledContents = $compile(contents, transclude);
}
compiledContents(scope, function(clone, scope) {
iElement.append(clone);
});
};
},
并将范围属性移至指令controller
函数
controller: function($scope) {
$scope.newLocation = {
name: 'xxx'
};
$scope.saveLocation = function() {
alert('save location');
};
}
这是更新后的DEMO
答案 1 :(得分:1)
我想我可能已经得到了它。模态不是开放式的,但我分叉 @K.Toress 的插件,我认为我的隔离范围正常。
http://plnkr.co/edit/8DwJqc?p=preview
重要的部分。
您需要使用控制器和指令。您需要控制器中的范围开始。
app.controller('MainCtrl', function($scope) {
$scope.locations = [{name: "loc1", level: 1}, {name: "loc2", level: 2}]
});
定义指令时,指令范围将具有directiveLocations
对象。
scope: {
directiveLocations: '=locations-attr'
},
它从元素的locations-attr属性获取此对象的名称,即&#34; locations&#34;。
<div class="modal" add-location-modal locations-attr="locations">
现在我们已将控制器$ scope.locations映射到指令范围内的directiveLocations。
要将位置保存回父控制器范围,只需附加到directiveLocations列表,因为它现在与父$ scope.locations相同。
var tempLocation = {
name: scope.newLocation.name,
level: scope.newLocation.level
}
scope.directiveLocations.push(tempLocation);
我不确定为什么我必须在这里创建一个新对象。将相同的对象添加回父作用域有一些奇怪的事情。