我有这个模板:
<div class="modal" id="popupModal" tabindex="-1" role="dialog" aria-labelledby="createBuildingLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="createBuildingLabel">{{ title }}</h4>
</div>
<form data-ng-submit="submit()">
<div class="modal-body" data-ng-transclude>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-ng-click="visible = false">Annuleren</button>
<button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-save"></span>Maken</button>
</div>
</form>
</div>
</div>
</div>
这是指令:
app.directive("modalPopup", [function () {
return {
restrict: 'E',
templateUrl: 'Utils/ModalPopup',
scope: {
title: '@',
onSubmit: '&',
visible: '='
},
transclude: true,
link: function (scope, element, attributes) {
var container = $("#popupModal");
scope.submit = function (newGroup) {
scope.onSubmit(newGroup);
}
scope.hide = function () {
container.modal('hide');
}
scope.show = function () {
container.modal('show');
}
scope.$watch('visible', function (newVal, oldVal) {
if (newVal === true) {
scope.show();
}
else {
scope.hide();
}
})
}
}
}]);
正如您所看到的,我已在指令中声明了我的form
标记,并且我还使用transclude
来确定表单的外观。现在我有这个:
<modal-popup title="Nieuwe groep aanmaken" data-on-submit="createGroup()" visible="showAddGroupForm">
<div class="row">
<div class="col-md-3">Kopieren van:</div>
<div class="col-md-8">
<select class="form-control" data-ng-model="newGroup.Year">
<option value="">Nieuw jaar</option>
<option data-ng-repeat="year in years" value="{{year.Id}}">{{year.Name}}</option>
</select>
</div>
</div>
<div class="row">
<div class="col-md-3">Naam</div>
<div class="col-md-8">
<input type="text" class="form-control" data-ng-model="newGroup.Name" />
</div>
</div>
</modal-popup>
按下提交按钮后,我希望数据在我的控制器中可用。
我认为由于隔离范围,数据不可用,但我不确定。我需要做什么才能将数据从指令恢复到我的控制器中?
PS:我知道angular-ui和angularstrap,但我这样做是为了了解Angular。
编辑:
这是Fiddle
答案 0 :(得分:3)
我认为原因是对范围如何运作的误解(特别是在进行翻译时)。
让我们从这个代码开始(来自小提琴):
<div ng-controller="MyCtrl">
<my-popup on-submit="formSubmitted(model)">
<input type="text" ng-model="model.Name"/>
</my-popup>
</div>
由于<my-popup>
转换了其内容,因此上述范围是MyCtrl
的范围,即使在指令的内容中也是如此。内容是指<input>
, NOT 指令模板,即<div><form ...
代码。
因此暗示model
(在ng-model="model.Name"
中使用)是MyCtrl
范围内的属性,formSubmitted()
也是如此。由于两者都是同一范围的成员,因此您无需将模型作为参数传递;你可以这么做:
(在模板中:)
<my-popup on-submit="formSubmitted()"><!-- no `model` argument -->
(控制器:)
function MyCtrl($scope) {
// I like declaring $scope members explicitly,
// though it can work without it (charlietfl comments)
$scope.model = {};
$scope.submittedValue = null;
$scope.formSubmitted = function() {
// another bug was here; `model` is always a member of the `$scope`
// object, not a local var
$scope.submittedValue = $scope.model.Name;
}
}
指令代码中还有另一个错误:
link: function(scope, element, attributes){
scope.submit = function(){
scope.onSubmit({model: model});
}
}
变量model
(不是名称model:
)未定义!它是父范围的属性,因此如果范围未被隔离,您将有机会。由于该指令的孤立范围,它可能与我甚至不打算写的可怕的解决方法一起工作:)
幸运的是,您不需要该指令来了解外部范围内发生的事情。该指令有一个函数,用于显示表单和提交按钮,并在单击提交按钮时调用回调。因此,以下内容不仅适用于此示例,而且在概念上也是正确的(指令并不关心它外面发生了什么):
link: function(scope, element, attributes){
scope.submit = function(){
scope.onSubmit();
}
}
请参阅小提琴:http://jsfiddle.net/PRnYg/
顺便说一下:你正在使用Angular v1.0.1。这是 WAAAAY 太老了,认真考虑升级!!!如果您执行升级,请将结束</div>
添加到模板:<div ng-transclude></div>
。