我知道这可以通过ui-router实现,而且在角度2中这不再是一个问题。但对于我们的实际项目,我们暂时陷入了角度1.x和$ routeProvider的困境。
所以我想要的是打开一个现有的组件(例如一个登录表单),它已经生活了#34;在它自己的页面中,或者在模态对话框($ uibModal)上,无需复制或修改它的控制器或模板。
最简单的示例是登录表单,拥有自己的路由,例如可以通过myapp/#/login
访问,现在我也希望将其显示在当前"页面的顶部"作为模态,无需修改控制器/模板等。当模态消失后,我希望下面的页面处于与我离开时相同的状态。
此解决方案适用于任何视图,而不仅仅是登录表单(作为示例)。所以我正在寻找通用的解决方案。
有什么想法吗?
答案 0 :(得分:0)
经过一番尝试,我终于得到了我想要的东西:
首先我创建了一个服务,它负责打开泛型模态。我叫它genericModalSvc
值得一提的是,我正在使用名为namedRouteSvc
的服务来获取
每个名字的路线和其他很酷的东西。路由名称定义为自定义
路线上的参数如下:
$routeProvider
.when('/something', {
name: 'something', // this is a custom parameter to retrieve the route
templateUrl: 'something.html',
controller: 'SomethingCtrl',
controllerAs: 'ctrl'
})
以上对于genericModalSvc来说不是必需的,但它可以解决问题 更容易理解下面的代码:
angular
.module('my_app.common_stuff')
.service('GenericModalSvc', GenericModalSvc);
GenericModalSvc.$inject = ['$uibModal', '$rootScope', 'namedRouteSvc'];
function GenericModalSvc($uibModal, $rootScope, namedRouteSvc) {
this.$uibModal = $uibModal;
this.$rootScope = $rootScope;
this.namedRouteSvc = namedRouteSvc;
this.modalInstance = null;
// Broadcasts for close signal from modal's close button
this.$rootScope.$on('GenericModalCloseClicked', this.close.bind(this));
}
GenericModalSvc.prototype.close = function() {
this.modalInstance.close();
// Emit a signal here, for other listeners to know the modal has been
// closed.
this.$rootScope.$emit('GENERIC_MODAL_CLOSED');
};
GenericModalSvc.prototype.open = function(params) {
// The params argument here, has route information and parameters I
// want to transfer to the model
var route_name = params.route_name, // A string defined in each route
args = params.args, // The route parameters
query = params.query, // The route query arguments
options = params.options; // Other options
this.$rootScope.$emit('GENERIC_MODAL_OPENED');
var route = this.namedRouteService.getRoute(route_name, args, query);
route = route.hasOwnProperty('route') ? route.route : null;
if (!route) {
throw new Error('Could not find a route for the given parameters');
}
var modal_title = params.options.modal_title;
// The following is the fun part. Now we can use the route to get the
// controller and controllerAs attributes to define our modal here.
this.modalInstance = this.$uibModal.open({
// This template is the modal wrapper for our 'real' template.
templateUrl: 'partials/generic-modal.html',
controller: route.controller,
controllerAs: route.controllerAs,
backdrop: 'static',
size: 'lg',
resolve: {
show_modal_close: function() {
return Boolean(options && options.showCloseButton);
},
modal_title: function() {
return modal_title;
},
template_to_render: function() {
// We need to pass this information to our generic-modal.html
// template to include it there.
return route.templateUrl;
},
dummy: function($routeParams) {
// This is a rather kind of q&d way of passing the route
// parameters and query arguments. On the controller, we
// must look inside $routeParams for 'modalParameters' first
// (because we don't know there if we're inside a modal or not)
// and if 'modalParameters' doesn't exist, then we retrieve the
// normal-ones inside $routeParams. I know, it's not perfect
// but didn't come up with a better idea.
$routeParams.modalParameters = {
routeParams: args,
queryParams: query
};
}
}
});
};
然后,generic-modal.html模板非常简单:
<p id="generic-modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"
ng-click="$emit('GenericModalCloseClicked')">
<span aria-hidden="true">X</span></button></p>
<div id="generic-modal-container">
<div ng-include="$resolve.template_to_render"></div>
</div>
最后这是一个如何使用它的例子:
angular
.module('my_app.foo')
.controller('FooCtrl', FooCtrl);
FooCtrl.$inject = ['...','genericModalSvc'];
function FooCtrl(..., genericModalSvc) {
this.genericModalSvc = genericModalSvc;
}
FooCtrl.prototype.openBarDetailsOnModal = function() {
var params = {
route_name: 'bar-detail',
args: {'id': this.some_id_for_bar},
query: {},
options: {}
};
this.genericModalSvc.open(params);
};
就是这样!!!