如何在angular 1.5中将angular component与ui.bootstrap.modal一起使用

How to use angular component with ui.bootstrap.modal in angular 1.5?

本文关键字:angular bootstrap ui modal 一起 component 中将      更新时间:2024-01-03

我想使用ui.bootstrap.modal的角度组件。角度版本是1.5。
我试着像下面这样使用。

组件

function MyComponentController($uibModalInstance){
  var ctrl = this;
  ctrl.doSomething = function() {
    //doSomething
  }
}
app.component('myComponent', {
  contoller: MyComponentController,
  templateUrl: '/path/to/myComponent.html'
}

父控制器

function parentController($uibModal){
  var ctrl = this;
  ctrl.openModal = function(){
    var modalInstance = $uibModal.open({
      template: '<my-component></my-component>'
  }
}

当我执行parentController.openModal()时,我得到了$injector:unp Unknown Provider的错误,尽管模式窗口是打开的
有没有一种方法可以将角度分量与ui.bootstrap.modal一起使用?如果你需要更多信息,请告诉我
非常感谢。

编辑
我有一种方法可以使用Renato Machado的ui.bootstrap.modal组件,谢谢Renato
但我觉得有点复杂,不方便。所以最后我认为最好在模态中使用component
模态是以常规方式打开的(只需在$uibModal.open({})中设置控制器和模板),模态中包含有您常用逻辑的组件
模态应该只有和模态相关的简单逻辑,比如关闭模态窗口
另一个主要与业务/应用程序相关的逻辑应该在组件中
它很容易被大众化。

EDIT:从UI Bootstrap 2.1.0开始,在引导模式中有对组件的本地支持。在2.1.0之后,似乎已经有几个快速发布来修复模式的一些问题,所以我一定会抓住最新的。

有关使用UI引导2.1.0+的版本,请参阅此Plunk

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

angular.module('app', ['ngAnimate', 'ui.bootstrap']);
angular.module('app')
  .component('myContent', {
     template: 'I am content! <button type="button" class="btn btn-default" ng-click="$ctrl.open()">Open Modal</button>',
     controller: function($uibModal) {
        $ctrl = this;
        $ctrl.dataForModal = {
        name: 'NameToEdit',
        value: 'ValueToEdit'
     }
    $ctrl.open = function() {
      $uibModal.open({
         component: "myModal",
         resolve: {
           modalData: function() {
             return $ctrl.dataForModal;
           }
         }
       }).result.then(function(result) {
            console.info("I was closed, so do what I need to do myContent's  controller now.  Result was->");
      console.info(result);
       }, function(reason) {
           console.info("I was dimissed, so do what I need to do myContent's controller now.  Reason was->" + reason);
       });
    };
  }
});
angular.module('app')
  .component('myModal', {
template: `<div class="modal-body"><div>{{$ctrl.greeting}}</div> 
<label>Name To Edit</label> <input ng-model="$ctrl.modalData.name"><br>
<label>Value To Edit</label> <input ng-model="$ctrl.modalData.value"><br>
<button class="btn btn-warning" type="button" ng-click="$ctrl.handleClose()">Close Modal</button>
<button class="btn btn-warning" type="button" ng-click="$ctrl.handleDismiss()">Dimiss Modal</button>
</div>`,
  bindings: {
    modalInstance: "<",
    resolve: "<"
  },
  controller: [function() {
    var $ctrl = this;
    $ctrl.$onInit = function() {
      $ctrl.modalData = $ctrl.resolve.modalData;
    }
    $ctrl.handleClose = function() {
      console.info("in handle close");
      $ctrl.modalInstance.close($ctrl.modalData);
    };
    $ctrl.handleDismiss = function() {
      console.info("in handle dismiss");
      $ctrl.modalInstance.dismiss("cancel");
    };
  }]
});

最初的答案如下:

前几天我也在想办法解决这个问题。我把我在这篇文章中找到的信息和这个链接结合起来,试图想出一种替代的方法来实现这一点。以下是我发现的一些帮助我的参考链接:

https://github.com/angular-ui/bootstrap/issues/5683

http://www.codelord.net/(这有助于理解将参数传递给组件中的回调)

这里还有一个Plunk:http://plnkr.co/edit/PjQdBUq0akXP2fn5sYZs?p=preview

我试图演示一个常见的现实世界场景,即使用模态编辑一些数据。

angular.module('app', ['ngAnimate', 'ui.bootstrap']);
angular.module('app')
.component('myContent', {
    template: 'I am content! <button type="button" class="btn btn-default" ng-click="$ctrl.open()">Open Modal</button>',
    controller: function($uibModal) {
        $ctrl = this;
        $ctrl.dataForModal = {
            name: 'NameToEdit',
            value: 'ValueToEdit'
        }
        $ctrl.open = function() {
            $uibModal.open({
                template: '<my-modal greeting="$ctrl.greeting" modal-data="$ctrl.modalData" $close="$close(result)" $dismiss="$dismiss(reason)"></my-modal>',
                controller: ['modalData', function(modalData) {
                    var $ctrl = this;
                    $ctrl.greeting = 'I am a modal!'
                    $ctrl.modalData = modalData;
                }],
                controllerAs: '$ctrl',
                resolve: {
                    modalData: $ctrl.dataForModal
                }
            }).result.then(function(result) {
                console.info("I was closed, so do what I need to do myContent's controller now and result was->");
                console.info(result);
            }, function(reason) {
                console.info("I was dimissed, so do what I need to do myContent's controller now and reason was->" + reason);
            });
        };
    }
});
angular.module('app')
.component('myModal', {
    template: `<div class="modal-body"><div>{{$ctrl.greeting}}</div> 
<label>Name To Edit</label> <input ng-model="$ctrl.modalData.name"><br>
<label>Value To Edit</label> <input ng-model="$ctrl.modalData.value"><br>
<button class="btn btn-warning" type="button" ng-click="$ctrl.handleClose()">Close Modal</button>
<button class="btn btn-warning" type="button" ng-click="$ctrl.handleDismiss()">Dimiss Modal</button>
</div>`,
    bindings: {
        $close: '&',
        $dismiss: '&',
        greeting: '<',
        modalData: '<'
    },
    controller: [function() {
        var $ctrl = this;
        $ctrl.handleClose = function() {
            console.info("in handle close");
            $ctrl.$close({
                result: $ctrl.modalData
            });
        };
        $ctrl.handleDismiss = function() {
            console.info("in handle dismiss");
            $ctrl.$dismiss({
                reason: 'cancel'
            });
        };
    }],
});

没有必要通过传递父控制器来使其更加复杂,您只需从显示模态的.组件中访问它。

组件

/**
 * @ngdoc component
 * @name fsad.component:video
 *
 * @description <fsad-video> component, in development...
 *
 */

(function () {
  'use strict';
  angular.module('fsad').component('fsadVideo', {
    bindings: {},
    templateUrl: function(appConstant){return appConstant.paths.modules.fsad + 'leefloon/fsad-video.html'},
    controller: controller
  });
  controller.$inject = ['$scope'];
  function controller($scope){
    var $ctrl = this;
    setDataModel();
    /****************************************************************/
    $ctrl.ui.close = close;
    /****************************************************************/
    function setDataModel(){
      $ctrl.ui = {};
    }
    function close(){
      $scope.$parent.$close();
    }
  }
}());

打开模式

  var modalInstance = $uibModal.open({
    backdrop: 'static',
    keyboard: true,
    backdropClick: false,
    template: '<fsad-video></fsad-video>',
    windowClass: 'edit-contactenblad',
  });

由于您声明模板是一个组件,因此$scope$父对象将始终指向模态实例。允许您访问$close()函数。

传递和接收数据

如果需要将数据传递给组件,或者从组件接收回数据,可以这样做。

  var modalInstance = $uibModal.open({
    backdrop: 'static',
    keyboard: true,
    backdropClick: false,
    template: '<fsad-video method="$ctrl.method" on-viewed="$ctrl.userHasViewedVideo(time)"></fsad-ideo>',
    controller: function(){
      this.method = method;
      this.userHasViewedVideo = function(time){}
    },
    controllerAs: '$ctrl',
    windowClass: 'edit-medewerker',
  });

顺便说一句,我正在使用这个结构样式指南来创建组件。

如果您想访问$uibModal的$close()$dismiss()函数,以及组件中的一些父数据和函数绑定,您可以按如下方式传递它们:

开放模式逻辑

$uibModal.open({
    template: '<login close="$close()" dismiss="$dismiss()" ' +
        'email="$ctrl.cookieEmail" check-login="$ctrl.ajaxLogin(user, pass)"></login>',
    controller: function () {
        this.cookieEmail = $cookies.get('savedEmail');
        this.ajaxLogin = AjaxLoginService.login;
    },
    controllerAs: '$ctrl'
});

模式登录组件

{
    templateUrl: 'view/login.html',
    bindings: {
        email: '<',
        checkLogin: '&',
        close: '&',
        dismiss: '&'
    },
    controller: function () {
        var viewModel = this;
        viewModel.password = '';
        viewModel.submit = function () {
            viewModel.checkLogin(
                { user: viewModel.email, pass: viewModel.password }
            ).then(function (success) {
                viewModel.close();
            });
        }
    }
}

模式HTML

<form ng-submit="$ctrl.submit()">
    <input type="text" ng-model="$ctrl.email" />
    <input type="password" ng-model="$ctrl.password" />
    <button type="button" ng-click="$ctrl.dismiss()">Cancel</button>
    <button type="submit">Login</button>
</form>

AngularJS 1.5文档有点稀疏,但它们显示了&绑定作为函数包装器的用法:https://docs.angularjs.org/guide/component

您需要将父控制器传递给带有模态实例的模态组件。为此,您需要在父组件中附加模态的生成HTML

父组件

$ctrl.openModal = function(){
    $ctrl.modalInstance = $uibModal.open({
        template: '<your-modal></your-modal>',
        appendTo : $document.find('parentComponent')
    });
}

模态分量

.component('yourModal', {
        templateUrl: 'path/to/modal.html',
        replace: true,
        require: {
            parent : '^parentComponent'
        },
        controller: ModalCtrl
    });
function ModalCtrl() {
    var $ctrl = this;
    $ctrl.$onInit = function(){
        var instance = $ctrl.parent.modalInstance;
        $ctrl.items = ['item1', 'item2', 'item3'];
        $ctrl.selected = {
            item: $ctrl.items[0]
        };
        $ctrl.ok = function () {
            instance.close($ctrl.selected);
        };
        $ctrl.cancel = function () {
            instance.dismiss('cancel');
        };
        instance.result.then(function (selectedItem) {
            $ctrl.selected = selectedItem;
        }, function () {
            console.log('Modal dismissed at: ' + new Date());
        });
    };

}

请小心,因为所需的控制器只有在$onUnit之后才可用。