angular-ui bootstrap $ modal service using using

时间:2021-09-28 11:53:15

The examples I see of using angular-ui/bootstrap's $modal always look something like this:

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

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

What if I want to use a directive, instead? Like this:

如果我想使用指令,该怎么办?喜欢这个:

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

The markup for my-modal-directive renders fine, and I've moved the controller property into the my-modal-directive definition object, but now getting this error from the my-modal-directive:

my-modal-directive的标记渲染很好,我已经将控制器属性移动到my-modal-directive定义对象中,但现在从my-modal-directive获取此错误:

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

Can anyone point me to an example where $modal uses a directive where that directive defines the controller?

任何人都能指出一个例子,其中$ modal使用指令定义控制器吗?

For example, this works, where I've replaced the templateUrl with a directive:

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

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

But when I move the controller from $modal.open() into the directive, that's when the error happens:

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

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

5 个解决方案

#1


5  

The issue you have is that you are trying to inject values which are not available for injection. Only values registered with the injector can be injected.

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

The logic of you code is also flawed, you are creating the modal in your main controller but trying to close it in the directive. Ideally, the modal should be triggered by the directive (via it's link function), and then you can ok/cancel it from there.

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

See my http://plnkr.co/edit/3p1rXAymd7BilyklgxKy?p=preview for one possible approach, I have kept the code that closes and cancels the modal in the main controller.

请参阅我的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


6  

The problem is that $modalInstance can only be injected in the controller that you provide to $modal.open. Check out the sources here:

问题是$ modalInstance只能在你提供给$ modal.open的控制器中注入。看看这里的消息来源:

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

In essence when you try to add $modalInstance as a dependency to your controller AngularJS looks for a registered global provider named $modalInstanceProvider. Now the trouble is, if you understood the code above, that $modalInstance is not a globally registered provider. It only "exists" as a dependency for the controller you pass to $modal.open.

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

If you read the rest of the code you'll notice that $modal.open returns modalInstance, maybe you can use that.

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

Something like 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
    }
} 

#3


3  

I create a directive to create modals easily. A modal content is based on a template view.

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

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,                    
                });
            });
        }
    };
});

Example how to use it:

示例如何使用它:

index.html

的index.html

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

hello.html

hello.html的

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

HelloCtrl.js

HelloCtrl.js

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

A modal view can have its own controller. Example:

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

hello.html (modified)

hello.html(已修改)

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

Hello2Ctrl.js

Hello2Ctrl.js

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

Observe that the modal output will be "Hello Worldsszz Xico", because the modal controller (HelloCtrl) will be rendered after view controller (Hello2).

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

Reference

参考

#4


2  

It's even more late reply, but someone may find it useful.

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

I have enhanced Fernando Felix answer and made my own quite flexible directive which communicates with the controller, which I think might be solution for this question.

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

Directive

指示

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);

Controller

调节器

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);

inline template

内联模板

<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>

It's one controller and template per popup type, then you can call it multiple times with:

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

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

You can initialize value with whatever - ie. object, array etc.

你可以用任何东西初始化价值 - 即。对象,数组等

or external template

或外部模板

Pretty much the same, just url changes and template file is used for template.

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

<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

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>

Modal size etc.

模态尺寸等

Just add parameter size="sm|lg" for the modal link/button ie. Click here to open the modal For standard size skip the parameter. You may enhance it yourself using link function attrs.

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

#5


1  

I'm kanda late replay put simplest way is to use

我是熊猫后期重播,最简单的方法是使用

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

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

This works form your directive controller.

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

#1


5  

The issue you have is that you are trying to inject values which are not available for injection. Only values registered with the injector can be injected.

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

The logic of you code is also flawed, you are creating the modal in your main controller but trying to close it in the directive. Ideally, the modal should be triggered by the directive (via it's link function), and then you can ok/cancel it from there.

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

See my http://plnkr.co/edit/3p1rXAymd7BilyklgxKy?p=preview for one possible approach, I have kept the code that closes and cancels the modal in the main controller.

请参阅我的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


6  

The problem is that $modalInstance can only be injected in the controller that you provide to $modal.open. Check out the sources here:

问题是$ modalInstance只能在你提供给$ modal.open的控制器中注入。看看这里的消息来源:

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

In essence when you try to add $modalInstance as a dependency to your controller AngularJS looks for a registered global provider named $modalInstanceProvider. Now the trouble is, if you understood the code above, that $modalInstance is not a globally registered provider. It only "exists" as a dependency for the controller you pass to $modal.open.

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

If you read the rest of the code you'll notice that $modal.open returns modalInstance, maybe you can use that.

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

Something like 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
    }
} 

#3


3  

I create a directive to create modals easily. A modal content is based on a template view.

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

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,                    
                });
            });
        }
    };
});

Example how to use it:

示例如何使用它:

index.html

的index.html

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

hello.html

hello.html的

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

HelloCtrl.js

HelloCtrl.js

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

A modal view can have its own controller. Example:

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

hello.html (modified)

hello.html(已修改)

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

Hello2Ctrl.js

Hello2Ctrl.js

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

Observe that the modal output will be "Hello Worldsszz Xico", because the modal controller (HelloCtrl) will be rendered after view controller (Hello2).

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

Reference

参考

#4


2  

It's even more late reply, but someone may find it useful.

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

I have enhanced Fernando Felix answer and made my own quite flexible directive which communicates with the controller, which I think might be solution for this question.

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

Directive

指示

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);

Controller

调节器

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);

inline template

内联模板

<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>

It's one controller and template per popup type, then you can call it multiple times with:

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

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

You can initialize value with whatever - ie. object, array etc.

你可以用任何东西初始化价值 - 即。对象,数组等

or external template

或外部模板

Pretty much the same, just url changes and template file is used for template.

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

<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

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>

Modal size etc.

模态尺寸等

Just add parameter size="sm|lg" for the modal link/button ie. Click here to open the modal For standard size skip the parameter. You may enhance it yourself using link function attrs.

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

#5


1  

I'm kanda late replay put simplest way is to use

我是熊猫后期重播,最简单的方法是使用

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

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

This works form your directive controller.

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