我正在使用Angular的UI Bootstrap来显示模态叠加,用户可以在选择框中选择一个项目。用户选择的值应该在覆盖图的控制器中可用,以发送回打开控制器。在模态的HTML中,这可以工作:
<select
ng-model="selectedItem"
ng-options="item for item in items">
</select>
Selected: <b>{{ selectedItem }}</b>
但在控制器中,这始终是未定义的:
$scope.selectedItem;
为什么我无法在控制器中访问此值?
我正在开发的项目还有一些移动部件(我使用的是typeahead和buttons指令而不是简单的选择)但我将这个问题简化为这个工作示例:http://plnkr.co/edit/lb0NAGLR8eEVrywA67EC?p=preview。在此示例中,当模态关闭时,模态中的选择应显示在父页面上。
答案 0 :(得分:2)
使用AngularUI Bootstrap创建模式对话框时,会创建一个新的子范围。
这意味着$scope
中的ModalInstanceCtrl
实际上是HTML范围的父范围。 (不要问我为什么这样建造它。)
要证明这一点,请更改
ng-model="selectedItem"
至ng-model="$parent.selectedItem"
并更改
Selected: <b>{{ selectedItem }}</b>
至Selected: <b>{{ $parent.selectedItem }}</b>
。
瞧!它有效。
更好的解决方案是更改ok()
方法以接受子范围selectedItem
,如下所示:
ng-click="ok(selectedItem)"
// Then, in the controller
$scope.ok = function (selectedItem) {
$modalInstance.close(selectedItem);
};
有关正在发生的事情的更完整说明,请阅读this article。
答案 1 :(得分:2)
除了在控制器中创建的HTML之外,它似乎为模式内的HTML创建子范围。打开模态时,请参阅this plunker中的ID。
所以要点是你在孩子的范围内设置'selectedItem',这在你可以在模态实例控制器中访问的范围内不可用。有两种方法可以解决这个问题:
选项1 在'ok'函数中取一个参数并将结果传递给HTML (plunker):
<button class="btn btn-primary" ng-click="ok(selectedItem)">OK</button>
JS:
$scope.ok = function (arg) {
$modalInstance.close(arg);
};
选项2 在控制器中创建一个将继承到子范围以设置属性的对象。这就是sample code的作用。
当selectedItem
由angular设置时,它在您的控制器一无所知的子范围上设置,并且它不会传播到父范围。如果在继承的对象上设置值,它将更改继承对象的属性,您可以在控制器(plunker)中访问它:
<select
ng-model="selected.Item"
ng-options="item for item in items">
</select>
JS:
$scope.ok = function () {
$modalInstance.close($scope.selected.Item);
};
答案 2 :(得分:0)
更改
$modalInstance.close($scope.selectedItem);
到
$modalInstance.close($scope.selected.item);
并在html中
<div class="modal-body">
<select
ng-model="selected.item"
ng-options="item for item in items">
</select>
Selected: <b>{{ selected.item }}</b>
</div>
更新了plnkr - http://plnkr.co/edit/TuwPqtNeQwBVeXU2ncIe?p=preview