是否可以在 AngularJS 中混合注入的依赖项和自定义参数?

Is it possible to mix injected dependencies with custom arguments in AngularJS?

我正在使用 UI Bootstrap 的 $uibModal 创建模态。我也在使用 UI Router 0.2.15,所以我想要的是在新模式中打开的状态。

这是我的配置函数中的内容:

    $stateProvider
    .state("mystate.substate1", {
        url: '...',
        template: '<div ui-view></div>',
        onEnter: showFirstCustomModal
    })
    .state("mystate.substate2", {
        url: '...',
        onEnter: showSecondCustomModal
    });

    // End of calling code

    function showFirstCustomModal($uibModal) {

        var options = {
            backdrop: 'static',
            templateUrl: '...',
            controller: 'Controller1',
            controllerAs: 'controller'
        };

        $uibModal.open(options);
    }

    function showSecondCustomModal($uibModal) {

        var options = {
            backdrop: 'static',
            templateUrl: '...',
            controller: 'Controller2',
        };

        $uibModal.open(options);
    }

以上两种模态方式非常相似。我想用通用方法替换它们:

    $stateProvider
    .state("mystate.substate1", {
        url: '...',
        onEnter: showGenericModal('some_template','SomeController1', 'alias1')
    })
    .state("mystate.substate2", {
        url: '...',
        onEnter: showGenericModal('some_other_template', 'SomeController2')
    });

    // End of calling code

    function showGenericModal(templateUrl, controller, controllerAlias, $uibModal) {

        var options = {
            backdrop: 'static',
            templateUrl: templateUrl,
            controller: controller
        };

        if(!!controllerAlias) {
            options.controllerAs: controllerAlias;
        }

        $uibModal.open(options);
    }

我把 $uibModal 作为最后一个参数,以避免它被重新分配。但我无法让它发挥作用。我得到的错误是

 Cannot read property 'open' of undefined

此外,我一直在阅读 this 并且我知道您必须使用 $injector 才能注入您的服务。但我认为 UI-Bootstrap.

已经处理好了

因为 $stateProvider 是在 config 块中定义的,所以 $uibModal 不能作为引用从那里传递。

无法在 Angular DI 中混合依赖项和普通参数。对于 onEnter 它应该是一个接受依赖项列表的函数。

上面的代码转换为:

onEnter: showGenericModal('some_other_template', 'SomeController2')

...

function showGenericModal(templateUrl, controller, controllerAlias) {
  return ['$uibModal', function ($uibModal) {
    ...
    $uibModal.open(options);
  }];
}

或者更好的方法:

onEnter: function (genericModal) {
  genericModal.show('some_other_template', 'SomeController2');
}

...

app.service('genericModal', function ($uibModal) {
  this.show = function (templateUrl, controller, controllerAlias) {
    ...
    $uibModal.open(options);
  }
});

@estus回答正确,不知道怎么没看到状态:"For onEnter it should be a function that accepts the list of dependencies.".

不过,我在这里让我的回答提供另一个角度。您可以定义一个服务来正确地包装和组织您的代码,以便在 onEnter 状态事件上调用自定义模式:

angular.module('app').service('AppModals', AppModals);

// or use /** @ngInject */ aswell
AppModals.$inject = ['$uibModal'];

function AppModals($uibModal) {
    this.open = function _generateModal(options) {
        var defaultOptions = {
            backdrop: 'static'
            // Any other default option
        };

        return $uibModal.open(angular.extend({}, defaultOptions, options);
    };
}

关于状态定义:

$stateProvider
    .state('app.state', {
        url: '/state-modal',
        template: '<ui-view></ui-view>',
        controller: 'DummyCtrl',
        controllerAs: 'dummy',
        onEnter: appState_onEnter
    });

// or use /** @ngInject */ aswell
appState_onEnter.$inject = ['$uibModal'];

function appState_onEnter(AppModals) {
    AppModals.open({
        templateUrl: 'modals/state-modal.html',
        controller: 'DummyCtrl',
        controllerAs: 'dummy'
    });
}