使用给定父级绑定控制器

时间:2015-04-03 15:48:35

标签: angularjs angularjs-scope angular-bootstrap

使用Angular Bootstrap和$ modal服务,我使用以下模板创建一个弹出窗口:

<div class="dialog modal-header" ng-show="header.length > 0">
    <h3 compile="header"></h3>
</div>
<div class="dialog modal-body">
    <div compile="bodyTemplate"></div>
</div>
<div class="dialog modal-footer">
    <button ng-repeat="button in buttons"
            ng-show="$parent.$eval(button.showExpression)"
            ng-class="button.class"
            ng-click="onButtonClick(button)">
        <div compile="button.template"/>
    </button>
</div>

我构建了一个弹出服务,帮助设置范围的默认值,以及从templateUrl加载bodyTemplate。

// snippit of my popup service
function show(modalOptions, scope) {

    // ....
    // load template from modalOptions.bodyTemplateUrl
    // ....

    var extendedModalOptions = {};
    angular.extend(extendedModalOptions, defaultModelOptions, modalOptions);

    extendedModalOptions.controller = function ($scope, $modalInstance) {
        angular.extend($scope, scope);

        // .... 
        // add to $scope additional properties from the extendedModalOptions 
        // such as the buttons array and loaded bodyTemplate
        // ....
    }
    $modal.open(extendedModalOptions);
}

我想要的是注入一个用于bodyTemplate的控制器,如下所示:

<div class="dialog modal-header" ng-show="header.length > 0">
    <h3 compile="header"></h3>
</div>

<!-- Note the addition of ng-controller here -->
<div class="dialog modal-body" ng-controller="bodyController">
    <div compile="bodyTemplate"></div>
</div>

<div class="dialog modal-footer">
    <button ng-repeat="button in buttons"
            ng-show="$parent.$eval(button.showExpression)"
            ng-class="button.class"
            ng-click="onButtonClick(button)">
        <div compile="button.template"/>
    </button>
</div>

这可能有效,但bodyController范围的$ parent现在是$ modal控制器的范围。我想使用不同的父母。

我希望能够使用我的弹出式服务:

// from inside CustomerController
popup.show({
    header: 'Test Popup',
    parentScope: $scope, // the current scope of CustomerController
    bodyTemplateUrl: 'testPopupTemplate.html',
    bodyController: 'TestPopupController as testPopupVM'
});

这是我有点迷失的地方。我认为我的弹出服务可以像这样创建控制器:

$scope.bodyController = $controller(extendedModalOptions.bodyController, {
    $scope: extendedModalOptions.parentScope
});

我不是100%肯定,但我认为这会让我拥有正确的父母控制器。但问题是返回的值是新的范围对象,而不是构造函数。

根据ng-controller上的角度文档,它只能绑定到构造函数。

如何在使用提供的父范围时将主体控制器添加到弹出模板?

2 个答案:

答案 0 :(得分:0)

您正在尝试创建自己的$scope层次结构,而Angular提供的层次结构正常。

默认情况下,使用$modal服务打开的模式会从$rootScope获取新的子范围。您可以通过明确设置基本模态范围来更改此设置,即

$modal({
    scope: yourBaseScope
    // other modal options
})

Modal会在创建时调用yourBaseScope.$new()并使用它。因此,它可以访问您在yourBaseScope

中定义的所有变量和函数

详细了解模态的范围in docs

答案 1 :(得分:0)

fracz的答案是更好的选择,但我想提供一个替代黑客。

由于ng-controller只能绑定到控制器功能,我在弹出服务中构建了一个:

$scope.bodyCtrl = function($scope) {
   // HACK: replace the parent with the one from extendedModalOptions
   $scope.$parent = extendedModalOptions.parentScope;

   return $controller(extendedModalOptions.bodyController, {
       $scope: $scope
   });
};
// annotate the controller function so minification does't break injection
$scope.bodyCtrl['$inject'] = ['$scope'];

手动替换范围上的$ parent有代码味道。我没有意识到你可以将$ rootScope替换为$ modal。