如何使用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.
    });