Angular UI模式的范围问题


80

我在理解/使用角度UI模式的范围时遇到麻烦。

虽然这里没有立即显示出来,但我已经正确地设置了模块和所有内容(据我所知),但是这些代码示例尤其是在我发现错误的地方。

index.html(重要部分)

<div class="btn-group">
    <button class="btn dropdown-toggle btn-mini" data-toggle="dropdown">
        Actions
        <span class="caret"></span>
    </button>
    <ul class="dropdown-menu pull-right text-left">
        <li><a ng-click="addSimpleGroup()">Add Simple</a></li>
        <li><a ng-click="open()">Add Custom</a></li>
        <li class="divider"></li>
        <li><a ng-click="doBulkDelete()">Remove Selected</a></li>
    </ul>
</div>

Controller.js(同样是重要部分)

MyApp.controller('AppListCtrl', function($scope, $modal){
    $scope.name = 'New Name';
    $scope.groupType = 'New Type';

    $scope.open = function(){
        var modalInstance = $modal.open({
            templateUrl: 'partials/create.html',
            controller: 'AppCreateCtrl'
        });
        modalInstance.result.then(function(response){

            // outputs an object {name: 'Custom Name', groupType: 'Custom Type'}
            // despite the user entering customized values
            console.log('response', response);

            // outputs "New Name", which is fine, makes sense to me.                
            console.log('name', $scope.name);

        });
    };
});

MyApp.controller('AppCreateCtrl', function($scope, $modalInstance){
    $scope.name = 'Custom Name';
    $scope.groupType = 'Custom Type';

    $scope.ok = function(){

        // outputs 'Custom Name' despite user entering "TEST 1"
        console.log('create name', $scope.name);

        // outputs 'Custom Type' despite user entering "TEST 2"
        console.log('create type', $scope.groupType);

        // outputs the $scope for AppCreateCtrl but name and groupType
        // still show as "Custom Name" and "Custom Type"
        // $scope.$id is "007"
        console.log('scope', $scope);

        // outputs what looks like the scope, but in this object the
        // values for name and groupType are "TEST 1" and "TEST 2" as expected.
        // this.$id is set to "009" so this != $scope
        console.log('this', this);

        // based on what modalInstance.result.then() is saying,
        // the values that are in this object are the original $scope ones
        // not the ones the user has just entered in the UI. no data binding?
        $modalInstance.close({
            name: $scope.name,
            groupType: $scope.groupType
        });
    };
});

create.html(全部)

<div class="modal-header">
    <button type="button" class="close" ng-click="cancel()">x</button>
    <h3 id="myModalLabel">Add Template Group</h3>
</div>
<div class="modal-body">
    <form>
        <fieldset>
            <label for="name">Group Name:</label>
            <input type="text" name="name" ng-model="name" />           
            <label for="groupType">Group Type:</label>
            <input type="text" name="groupType" ng-model="groupType" />
        </fieldset>
    </form>
</div>
<div class="modal-footer">
    <button class="btn" ng-click="cancel()">Cancel</button>
    <button class="btn btn-primary" ng-click="ok()">Add</button>
</div>

因此,我的问题是:为什么作用域未与UI双重绑定?为什么this有自定义的值,但$scope没有?

我试图ng-controller="AppCreateCtrl"在create.html中添加到div正文中,但这引发了错误:“未知提供程序:$ modalInstanceProvider <-$ modalInstance”,因此没有运气。

在这一点上,我唯一的选择是使用this.namethis.groupType而不是使用来传递对象$scope,但这感觉不对。


良好的模态范围讨论在这里:github.com/mgcrea/angular-strap/issues/14
steampowered

Answers:


60

我让我这样工作:

var modalInstance = $modal.open({
  templateUrl: 'partials/create.html',
  controller: 'AppCreateCtrl',
  scope: $scope // <-- I added this
});

没有表单名称,没有$parent。我正在使用AngularUI Bootstrap版本0.12.1。

我通风报信该解决方案通过


这是一个更好的解决方案。干净得多。我们最近刚刚升级到0.12.1,目前正在修复它引入的重大更改。我可以将其添加到列表中。谢谢!!
coblr 2015年

我接受这个答案,因为它是当前的实现,对于最终尝试使事情正常进行的人来说将更加有用。除非您使用的是最新(〜0.12)版本的Angular UI,否则请阅读完整的主题。
coblr 2015年

如果在设置了范围的情况下状态发生了变化,则$ modalStack似乎无法关闭该模态
phazei 2015年

嗨,这解决了我一段时间的问题,但是在关闭模态/对话框时发现了一件奇怪的事情,内容正在更改,并且似乎与作用域对象上的东西混淆了。添加范围:$ scope,preserveScope:true // <-重要的帮助!不确定为什么,但是在material.angularjs.org/latest/api/service/…上找到了。编辑:我找到了原因。当您为对话框设置作用域:时,然后关闭对话框“除非将saveScope设置为true,否则删除底部工作表时,此作用域将被破坏。”
马克斯

在我的控制器中,我正在使用vm = this。我没有使用$ scope。那我应该分配什么范围呢?
Ankit Prajapati

66

当涉及嵌套作用域时,请勿将<input>s直接绑定到作用域成员:

<input ng-model="name" /> <!-- NO -->

将它们绑定到至少一个更深的层次:

<input ng-model="form.name" /> <!-- YES -->

原因是作用域原型继承了其父作用域。因此,在设置第一级成员时,这些成员将直接设置在子级作用域上,而不会影响父级。与此相反,当绑定到嵌套字段(form.name)时,该成员form是从父作用域中读取的,因此访问name属性将访问正确的目标。

在此处阅读更详细的说明。


14
虽然将其更改为“ form.name”并没有任何作用,但将其更改为ng-model =“ $ parent.name”可以解决此问题。谢谢!(也感谢您的阅读材料。还没有看过。)
coblr 2013年

1
如果使用controller as语法,则不会遇到这样的嵌套范围问题
rob

什么是controller as 语法?
adrianboimvaser 2014年

1
参见docs.angularjs.org/api/ng.directive:ngController。基本上做ng-controller =“ MyCtrl as my”然后引用像my.someVar这样的ng模型
Ryan Q

2
@Nikos Paraskevopoulos,“ form.name”代表什么?提供的代码中根本没有提到它!
ŁukaszBachman

7

2014年11月更新

实际上,在升级到ui-bootstrap 0.12.0之后,您的代码应该可以工作。超越范围与控制器的范围合并在一起,因此不再需要$parentform.填充任何东西。

在0.12.0之前

模态使用插入来插入其内容。多亏了ngForm您可以通过name属性控制范围。因此,要逃避包含范围,只需修改表单即可:

<form name="$parent">

要么

<form name="$parent.myFormData">

模型数据将在控制器范围内可用。


明确地说,您是说要在其中调用的控制器的范围对$modal分配给模态的控制器可用吗?
2015年

不,问题在于表单甚至都不容易访问模式实例控制器。要访问打开模态的控制器,只需将其scope:$scope放在$ modal.open params映射中。
Gertas,2015年

您是说Angular UI吗?这与UI Bootstrap有什么不同吗?
诺亚

1
$scope.open = function () {

          var modalInstance = $uibModal.open({
              animation: $scope.animationsEnabled,
              templateUrl: 'myModalContent.html',
              controller: 'salespersonReportController',
              //size: size
              scope: $scope
            });

      };

适用范围:$ scope Thank you Jason Swett


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.