如何使用durandal路由器激活对话框?
我想要一个#登录路径,在之前的任何页面上打开一个对话框如何使用durandal路由器激活对话框?,durandal,durandal-2.0,durandal-navigation,Durandal,Durandal 2.0,Durandal Navigation,我想要一个#登录路径,在之前的任何页面上打开一个对话框 让我们考虑下面的例子: router.map([ {route: '', moduleId: 'vm/home', title: "Home"}, {route: 'about', moduleId: 'vm/about', title: "About"}, {route: 'signin', moduleId: 'vm/signin', title: 'Sign In'} ]); 以下是示例用例: 用户在#上并导
让我们考虑下面的例子:
router.map([
{route: '', moduleId: 'vm/home', title: "Home"},
{route: 'about', moduleId: 'vm/about', title: "About"},
{route: 'signin', moduleId: 'vm/signin', title: 'Sign In'}
]);
以下是示例用例:
#
上并导航到#登录
:我们应该在主页上看到一个登录对话框#about
上并导航到#Sign
:我们应该在about页面顶部看到一个登录对话框http://localhost:9000/#signin
:我们应该在主页页面顶部看到一个登录对话框对话框和路由器都是插件,彼此之间没有交互 还有一个路由器显示对话框会忽略路由器的工作方式——它有一个div,可以将内容转储到其中。对话框存在于所有这些之外 但是如果你想(我也可以这么做),你可以试试这个 将
对话框:true
添加到路线图
重写router.loadUrl
方法。检查路由是否是我们之前标记的对话路由,并激活该对话框
我会将对话框设置为子管线,这样您就可以知道在对话框下方显示哪个视图。否则,您可能只需在任何内容上显示对话框,而完全忽略路由
编辑:我认为这实际上并不完全有效loadUrl
返回一个布尔值。您可以打开对话框并返回false以取消导航
编辑2:
我的尝试
loadUrl
方法在所有路由中循环,每个路由都有一个回调,因此理想情况下我们需要将逻辑插入这个数组
for (var i = 0; i < handlers.length; i++) {
var current = handlers[i];
if (current.routePattern.test(coreFragment)) {
current.callback(coreFragment, queryString);
return true;
}
}
所有者的想法是,如果初始路线是这样的,那么我们需要在对话框后面有一些东西
现在将路由器.路由
调用配置路由
替换为:
router.route(config.routePattern, function (fragment, queryString) {
if (config.dialog) {
if (!router.activeInstruction()) {
// No current instruction, so load one to sit in the background (and go back to)
var loadBackDrop = function (hash) {
var backDropConfig = ko.utils.arrayFirst(router.routes, function (r) {
return r.hash == hash;
});
if (!backDropConfig) {
return false;
}
history.navigate(backDropConfig.hash, { trigger: false, replace: true });
history.navigate(fragment, { trigger: false, replace: false });
queueInstruction({
fragment: backDropConfig.hash,
queryString: "",
config: backDropConfig,
params: [],
queryParams: {}
});
return true;
};
if (typeof config.owner == 'string') {
if (!loadBackDrop(config.owner)) {
delete config.owner;
}
}
if (typeof config.owner != 'string') {
if (!loadBackDrop("")) {
router.navigate("");
return; // failed
}
}
}
var navigatingAway = false;
var subscription = router.activeInstruction.subscribe(function (newValue) {
subscription.dispose();
navigatingAway = true;
system.acquire(config.moduleId).then(function (dialogInstance) {
dialog.close(dialogInstance);
});
})
// Have a route. Go back to it after dialog
var paramInfo = createParams(config.routePattern, fragment, queryString);
paramInfo.params.unshift(config.moduleId);
dialog.show.apply(dialog, paramInfo.params)
.always(function () {
if (!navigatingAway) {
router.navigateBack();
}
});
} else {
var paramInfo = createParams(config.routePattern, fragment, queryString);
queueInstruction({
fragment: fragment,
queryString: queryString,
config: config,
params: paramInfo.params,
queryParams: paramInfo.queryParams
});
}
});
确保将
对话框
导入模块。在评论中扩展我的建议,也许类似的方法会奏效。只需在router:route:activating
或其他类似事件之一上配置事件挂钩,并拦截/#signin
的激活。然后使用此挂钩作为显示对话框的方式。请注意,此示例用于说明目的。我无法在工作时提供工作示例。:/我可以在回家后完成,但至少这给了你一个想法
router.on('router:route:activating').then(function (instance, instruction) {
// TODO: Inspect the instruction for the sign in route, then show the sign in
// dialog and cancel route navigation.
});
在使用home viewmodel的激活数据时,可能不需要所有这些。 看看我的答案,我创造了 这个想法是路由接受一个可选的激活数据,家庭VM的激活方法可以检查该数据,并相应地显示所需的模式 这样做的好处是,您根本不需要接触现有的Durandal插件或核心代码。 但我不确定这是否完全符合您的要求,因为要求没有详细说明 更新: 好的,我现在已经更新了回购协议,以满足推广的额外要求。本质上,现在我们在shell中利用Durandal的Pub/Sub机制,或者将其放置在任何您想要的地方。在那里,我们监听路由器导航完成事件。发生这种情况时,检查指令集并搜索给定的关键字。如果是这样的话,则触发模态。通过使用navigation complete事件,我们还可以确保主VM正确且完全加载。
对于那些你想导航到#signin的黑客,只需手动将它们重新路由到你想去的任何地方。可能重复@Tambo,它不是重复的,op正在寻找一个没有路由的对话框,我正在寻找一个解决方案,其中对话框类似于有自己路由的
页面
。我很想看看一个例子!我不清楚在loadUrl
中覆盖什么,因为它基本上只是将路由与模式匹配。我将在某个时候尝试一下。我刚刚开始使用儿童路由器,所以它对我来说也是非常新的!另一种可能性是,您可以连接到许多路由器事件中的一个,如router:route:activating
,并在那里处理该对话框。@Brett,我已经启动了一个最大可能大小的悬赏,所以欢迎您用一些代码片段来回答。我已经尝试过了。在webapp中使用感觉很好,但我真的不喜欢编辑durandal模块本身的方式。这似乎是一个优雅的解决方案。以你的时间为例。回购协议+1,但有一点你错过了。我真的希望对话框在以前的任何页面上打开。您的解决方案需要修复您可以从中登录的每个潜在viewmodel。你能想出一个更一般化的解决方案吗?我已经更新到问题,以更好地说明可能的用例,请看一看!看起来好多了。但是你的例子仍然有一些问题。我注意到登录
路由器与主页
路由绑定。那么,如果我要添加路由about
,我是否也必须添加about(/:showmodel)
?这是我试图避免的。另一个更新添加了关于。。。基本上,当您需要另一条管线时,只需添加普通管线,但包括可选(/:showmodel)参数。因此,它能够服务于模态/非模态视图。没有将signin绑定到任何东西,因为现在观察到路由器事件,并且只检查当前路由指令。这样,您就可以对多个路由重复使用该模式。这是不可取的。我真正想要的是一条不与任何页面绑定的#登录
路线。任何页面都可能包含自己的页面
router.on('router:route:activating').then(function (instance, instruction) {
// TODO: Inspect the instruction for the sign in route, then show the sign in
// dialog and cancel route navigation.
});