如何使用 $routeProvider 在 AngularJS 1.x 中的 ui-modal 中打开现有的 controller/view
How to open an existing controller/view in an ui-modal in AngularJS 1.x with $routeProvider
我知道 ui-router 可以做到这一点,而且在 angular 2 中这不再是问题。但是对于我们的实际项目,我们暂时受困于 angular 1.x 和 $routeProvider。
所以我想要的是打开一个现有的组件(例如登录表单),它已经 "lives" 在它自己的页面中,或者在模式对话框($uibModal)上必须复制或修改它的控制器或模板。
最简单的例子是登录表单,它有自己的路由,例如可通过 myapp/#/login
访问,现在我还想将其作为模式显示在当前 "page" 的顶部,而无需修改 controller/template 等。当模式消失时,我想要下面的页面与我离开时的状态相同。
此解决方案适用于任何视图,而不仅仅是登录表单(例如)。所以我正在寻找通用解决方案。
有什么想法吗?
经过一番尝试,我终于得到了我要找的东西:
首先我创建了一个服务,它负责打开通用模式。我叫它 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);
};
就是这样了!!!
我知道 ui-router 可以做到这一点,而且在 angular 2 中这不再是问题。但是对于我们的实际项目,我们暂时受困于 angular 1.x 和 $routeProvider。
所以我想要的是打开一个现有的组件(例如登录表单),它已经 "lives" 在它自己的页面中,或者在模式对话框($uibModal)上必须复制或修改它的控制器或模板。
最简单的例子是登录表单,它有自己的路由,例如可通过 myapp/#/login
访问,现在我还想将其作为模式显示在当前 "page" 的顶部,而无需修改 controller/template 等。当模式消失时,我想要下面的页面与我离开时的状态相同。
此解决方案适用于任何视图,而不仅仅是登录表单(例如)。所以我正在寻找通用解决方案。
有什么想法吗?
经过一番尝试,我终于得到了我要找的东西:
首先我创建了一个服务,它负责打开通用模式。我叫它 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);
};
就是这样了!!!