angular-ui bootstrap $ modal service using using

时间:2015-02-18 16:14:48

标签: javascript angularjs angular-ui angular-ui-bootstrap

我看到使用angular-ui / bootstrap的$modal的例子看起来总是这样:

    $modal.open({
        templateUrl: 'modaltemplate.html',
        controller: function($scope) {
            ...
        }
    });

如果我想使用指令,该怎么办?像这样:

    $modal.open({
        template: '<my-modal-directive></my-modal-directive>'
        // no "controller" property; use directive's controller
    });

my-modal-directive的标记呈现正常,我已将controller属性移动到my-modal-directive定义对象中,但现在从my-modal-directive获取此错误:< / p>

Error: [$injector:unpr] Unknown provider: $modalInstanceProvider <- $modalInstance

有人能指出一个例子$modal使用指令定义controller吗?

例如,这有效,我用指令替换了templateUrl

http://plnkr.co/edit/YrGaF83GH6bzZPRR55GK?p=preview

但是当我将控制器从$modal.open()移动到指令中时,就会发生错误:

http://plnkr.co/edit/aLBT239EpL004DRh4jll?p=preview

5 个答案:

答案 0 :(得分:6)

问题是$modalInstance只能注入您提供给$modal.open的控制器中。 查看来源here

$modal.open = function (modalOptions) {
    ...
    var modalInstance = {
        ...
    };
    ...
    if (modalOptions.controller) {
        ...
        ctrlLocals.$modalInstance = modalInstance;
        ...
        ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
        ...
    }
    ...
}

实质上,当您尝试将$modalInstance作为依赖项添加到控制器时,AngularJS会查找名为$modalInstanceProvider的已注册全局提供程序。现在问题是,如果您理解上面的代码,$modalInstance 是全球注册的提供商。只有&#34;存在&#34;作为传递给$modal.open的控制器的依赖项。

如果您阅读了其余代码,您会注意到$modal.open返回modalInstance,也许您可​​以使用该代码。

this

function SomeController($modal) {
    $scope.modal = {
        instance: null
    };

    $scope.modal.instance = $modal.open({
        template: '<my-modal-directive modal="modal"></my-modal-directive>',
        scope: $scope
    });
}

function MyModalDirective() {
    scope: {
        modal: '='
    },
    link: function($scope) {
         // here you can access $scope.modal.instance
    }
} 

答案 1 :(得分:5)

您遇到的问题是您正在尝试注入无法注入的值。只能注入注射器注册的值。

您的代码逻辑也有缺陷,您在主控制器中创建模态但尝试在指令中关闭它。理想情况下,模态应该由指令触发(通过它的链接功能),然后你可以从那里确定/取消它。

有关一种可能的方法,请参阅我的http://plnkr.co/edit/3p1rXAymd7BilyklgxKy?p=preview,我保留了关闭的代码并取消了主控制器中的模式。

    angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
angular.module('ui.bootstrap.demo').directive('myModal', function() {
    return {
        restrict: 'E',
        templateUrl: 'myModalContent.html',
        controller: function ($scope) {
          $scope.selected = {
            item: $scope.items[0] 
          };
        }
    };
});
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope, $modal, $log) {

  $scope.items = ['item1', 'item2', 'item3'];

  $scope.open = function (size) {
    var modalInstance;
    var modalScope = $scope.$new();
    modalScope.ok = function () {
            modalInstance.close(modalScope.selected);
    };
    modalScope.cancel = function () {
            modalInstance.dismiss('cancel');
    };      

    modalInstance = $modal.open({
      template: '<my-modal></my-modal>',
      size: size,
      scope: modalScope
      }
    );

    modalInstance.result.then(function (selectedItem) {
      $scope.selected = selectedItem;
    }, function () {
      $log.info('Modal dismissed at: ' + new Date());
    });
  };
});

答案 2 :(得分:3)

我创建了一个指令来轻松创建模态。模态内容基于模板视图。

angular.module('your_app').directive('modalViewUrl', function ($modal) {

    return {
        restrict: 'A', // A: attribute
        scope: { // isolate scope
            'modalViewUrl': '@', // modal view url to render the modal content
            'modalController': '@' // modal view controller (optional)
        },
        link: function($scope, element, attrs){

            element.bind('click', function(){

                var template = 
                    '<div class="modal-body">' + 
                    '<button ng-click="$close()" type="button" class="close" aria-label="Close">' +
                    '<span aria-hidden="true">&times;</span>' +
                    '</button>' +
                    '<div ng-include="\'' + $scope.modalViewUrl + '\'"></div>' +
                    '</div>';

                // see modal reference from ui bootstrap at <http://angular-ui.github.io>
                var modalInstance = $modal.open({
                    animation: true,
                    template: template,
                    controller: $scope.modalController,                    
                });
            });
        }
    };
});

如何使用它的示例:

<强>的index.html

<a modal-view-url="hello.html" modal-controller="HelloCtrl" href="#">
    Click here to open the modal
</a>

<强> hello.html的

<h1> Hello World {{name}} </h1>

<强> HelloCtrl.js

angular.module('yourApp').controller('HelloCtrl', 
                function ($scope, $modalInstance) {
    // $modalInstance: same from  from ui bootstrap
    $scope.name = "Xico";
});

模态视图可以有自己的控制器。例如:

hello.html(已修改)

<h1 ng-controller="Hello2Ctrl"> {{msg}} {{name}} </h1>

<强> Hello2Ctrl.js

angular.module('yourApp').controller('Hello2Ctrl', 
                function ($scope) {
    $scope.msg = "Hello Worldsszz";
    $scope.name = "Zefa";
});

观察模态输出为“Hello Worldsszz Xico”,因为模态控制器(HelloCtrl)将在视图控制器(Hello2)之后呈现。

Reference

答案 3 :(得分:2)

它的回复更晚,但有人可能会发现它很有用。

我已经加强了Fernando Felix的答案,并制定了我自己非常灵活的指令,与控制器进行通信,我认为这可能是解决这个问题的方法。

<强>指令

var modalUrl = function ($modal) {
    return {
        restrict: 'A', // A: attribute
        scope: { // isolate scope
            'modalUrl': '@', // modal view url to render the modal content
            'modalController': '@', // modal view controller (optional)
            'value': "="
        },
        link: function(scope, element, attrs){
            console.log('modalUrl link');

            var modalInstance;
            var template = [
                    '<div class="modal-body">',
                        '<button ng-click="$close()" type="button" class="close" aria-label="Close">',
                            '<span aria-hidden="true">&times;</span>',
                        '</button>',
                        '<div ng-include="\'' + scope.modalUrl + '\'"></div>',
                    '</div>'
                ].join('');


            element.bind('click', function(){
                // see modal reference from ui bootstrap at <http://angular-ui.github.io>
                modalInstance = $modal.open({
                    size: attrs.size,
                    animation: true,
                    template: template,
                    resolve: {
                        params: function () {
                            console.log('value passed to modal:');
                            console.log(scope.value);
                            return scope.value;
                        }
                    },
                    controller: scope.modalController
                });

                modalInstance.result.then(
                    function (returnValue) {
                        // alert('value: '+returnValue);
                        console.log('modal returnValue:');
                        console.log(returnValue);
                        scope.value = returnValue;
                    }, function () {
                        console.log('Modal dismissed at: ' + new Date());
                    }
                );

            });

        }
    };
}
modalUrl.$inject = ['$modal'];
angular.module('app').directive('modalUrl', modalUrl);

<强>控制器

var HelloCtrl = function ($scope, $modalInstance, modalVal) {
    // $modalInstance: same from  from ui bootstrap
    console.log('Hello init!');
    // modalVal is the init modal value passed via directive
    console.log(modalVal);

    // your code
    $scope.name = modalVal;

    $scope.ok = function() {                                        
        $modalInstance.close(this.name); // returnValue
    };

    $scope.cancel = function() {
        $modalInstance.dismiss('cancel');
    };
}
HelloCtrl.$inject = ['$scope', '$modalInstance','params'];
angular.module('app').controller('HelloCtrl',HelloCtrl);

内嵌模板

<script type="text/ng-template" id="hello.html">
    <div class="modal-header">
        <h3 class="modal-title">I'm a modal!</h3>
    </div>
    <div class="modal-body">
        <input type="text" ng-model="name" />                                        
    </div>
    <div class="modal-footer">
        <button class="btn btn-primary" ng-click="ok()">OK</button>
        <button class="btn" ng-click="cancel()">Cancel</button>
    </div>
</script>

每个弹出窗口类型有一个控制器和模板,然后您可以多次调用它:

<a modal-url="hello.html" modal-controller="HelloCtrl" value="yourVal" ng-init="yourVal='test'" href="#">Click here to open the modal</a>

您可以使用任何内容初始化值 - 即。对象,数组等。

或外部模板

几乎相同,只是网址更改和模板文件用于模板。

<a modal-url="/modal/test1.html" modal-controller="HelloCtrl" value="yourVal" ng-init="yourVal='test'" href="#">Click here to open the modal</a>

test1.html

<div class="modal-header">
    <h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
    <input type="text" ng-model="name" />                                        
</div>
<div class="modal-footer">
    <button class="btn btn-primary" ng-click="ok()">OK</button>
    <button class="btn" ng-click="cancel()">Cancel</button>
</div>

模态大小等

只需添加参数大小=&#34; sm | lg&#34;对于模态链接/按钮即。 单击此处打开模态 对于标准尺寸,请跳过参数。 您可以使用链接功能attrs自行增强它。

答案 4 :(得分:1)

我是神田后期重播,最简单的方法是使用

$scope.$parent.$close(result);

$scope.$parent.$dismiss(reason);

这适用于您的指令控制器。