Durandaljs从json生成子菜单

Durandaljs从json生成子菜单,json,knockout.js,durandal-2.0,Json,Knockout.js,Durandal 2.0,好吧,我对杜兰达尔还不太熟悉。我真的很难做到这一点 以下是我正在尝试做的:有一个主导航,它包含收件箱、草稿、提交等。单击这些,用户会看到主导航旁边的子菜单。此子菜单由我从服务器获取的json数据生成。单击子菜单中的选项应根据文档id在查看器viewmodel中打开文档 前 用户点击收件箱 2.菜单将显示收件箱中的文档。用户点击查看 3.单击的文档将显示给用户。 4.所以当他们说到这一点时,我希望url是mysite.com/inbox/viewer/123456 123456是documenti

好吧,我对杜兰达尔还不太熟悉。我真的很难做到这一点

以下是我正在尝试做的:有一个主导航,它包含收件箱、草稿、提交等。单击这些,用户会看到主导航旁边的子菜单。此子菜单由我从服务器获取的json数据生成。单击子菜单中的选项应根据文档id在查看器viewmodel中打开文档

用户点击收件箱 2.菜单将显示收件箱中的文档。用户点击查看 3.单击的文档将显示给用户。 4.所以当他们说到这一点时,我希望url是mysite.com/inbox/viewer/123456 123456是documentid

我只是没能找到与此类似的好例子,我想知道是否有人能帮我指出正确的方向

我通过将每个主导航链接制作成一个模块,在每个模块中都有一个文档窗口,但我认为必须有更好的方法。所以我要做的就是保持我的亚航行状态。我不想为我的每个主要导航项都设置一个模块

下面是我的shell代码: shell.js

define(['durandal/system', 'services/logger', 'plugins/router', 'durandal/activator'], function (system, logger, router, activator) {


    //#region Internal Methods      

    function log(msg, data, showToast) {
        logger.log(msg, data, system.getModuleId(shell), showToast);
    }

    function logError(msg, data, showToast) {
        logger.logError(msg, data, system.getModuleId(shell), showToast);
    }


    function navigateRoute(hashValue) {
        var target = hashValue.hash;

        $("body").addClass("subnav-active");
        document.cookie = "subNav=true";

        $(target).addClass("current");
        router.navigate(target, {replace: true, trigger: false });

    }



    var routes = [
            { route: '', hash: '#home', moduleId: 'home', title: '', nav: false, cssClass: 'icon-inbox' },
            { route: 'inbox', hash: '#inbox', moduleId: 'inbox', title: 'Inbox', nav: true, cssClass: 'icon-inbox' },
            { route: 'drafts', hash: '#drafts', moduleId: 'drafts', title: 'Drafts', nav: true, cssClass: 'icon-file-alt' },
            { route: 'submitted', hash: '#submitted', moduleId: 'submitted', title: 'Submitted', nav: true, cssClass: 'icon-hand-right' },
            { route: 'completed', hash: '#completed', moduleId: 'completed', title: 'Completed', nav: true, cssClass: 'icon-check' },
            { route: 'settings', hash: '#settings', moduleId: 'settings', title: 'Settings', nav: true, cssClass: 'icon-cog' }
    ];
    //#endregion

    var shell = {
        activate: function () {
            router.on('router:route:not-found', function (fragment) {
                logError('No Route Found', fragment, true);
            });

            return router.makeRelative({ moduleId: 'viewmodels' }) // router will look here for viewmodels by convention
                .map(routes)            // Map the routes
                .buildNavigationModel() // Finds all nav routes and readies them
                .activate();            // Activate the router
        }
        ,
        router: router,
        navigateRoute: navigateRoute
    };
    return shell;
});
shell.html

<div class="main-wrapper wrapper">
<div class="container_template">
    <header class="pageheader">
        <nav class="mobile-nav">
            <a class="menu-button" href="#main-navigation">
                <i class="icon-reorder"></i><span>Menu</span>
            </a>
        </nav>

        <h1 class="logo">template</h1>
        <nav class="nav-user">
            <a class="close" href="#">
                <i class="icon-chevron-right"></i>
                <span>Main</span>
            </a>
        </nav>
    </header>

    <!-- Begin Header/Navigation -->
    <div class="main-navigation" role="banner">
        <div class="main-navigation-inner inner">
            <nav class="navigation">
                <ul data-bind="foreach: router.navigationModel">
                    <li>
                        <a class="nav-button" data-bind="attr: {'data-target': hash,}, css: {'nav-button' : isActive, active: isActive }, click: function(hash) { $root.navigateRoute(hash);return true},">
                            <i data-bind="css: cssClass"></i>
                            <span data-bind="html: title"></span>
                        </a>

                    </li>
                </ul>
            </nav>
        </div>
    </div>
    <!-- End Header/Navigation -->
    <!-- Sub Navigation Elements -->
    <!--This is my sbumenu-->
    <div id="inbox" class="navigation-sub">
        <div class="navigation-sub-inner inner">

            <div class="navigation-sub-header">
                <a class="close" href="#">&times;</a>
                <h3>Inbox</h3>
            </div>

            <div class="navigation-sub-search">
                <form>
                    <input type="text" placeholder="Search" />
                    <button>Go</button>
                </form>
            </div>
            <ul data-bind="contentsOfInbox">
                <li>
                    <a data-bind="href : linktoDocuemntViewer" href="" class="form-open">

                        <i class="icon-file-alt"></i><span data-bind="html: NameofDocumentHere"></span>
                        <span class="date" data-bind="html: DateOfDocumentHere"></span>
                    </a>
                </li>
            </ul>
        </div>
    </div>

    <!-- End SUB NAV -->
    <!--Begin Main-->
    <!--Documents would appear here-->
    <div class="main" data-bind=" router: { cacheViews: false }">


    </div>
    <!-- End Main -->
</div>


感谢您提供的任何帮助

您正在尝试做的事情听起来好像使用navigationModel无法工作。根据我的经验,navigationModel和route是一对一的关系。您要做的是将一个路由的参数绑定到多个菜单项。要做到这一点,你应该分开你的菜单和路线。记住,一切的核心是将javascript对象和集合绑定到html元素。router.navigationModel属性只是一个javascript对象的集合,它是根据定义的路由构建的。当您调用.buildNavigationModel时,它正在做的就是建立一个新的javascript对象集合,以便绑定到菜单html。没有什么可以阻止您在shell viewmodel上创建一个全新的属性,该属性包含您自己的javascript菜单对象自定义集合,并将其绑定到UL/LI导航html。如果您将这个新的菜单集合设置为computedObservable,那么您可以根据需要以惰性的方式添加到其中,并且由于它与knockout绑定,因此更改将自动出现在UI中。我在许多不同的项目上都做过,效果很好。我在后端构建了一个菜单表,然后只返回用户有权访问的项目,并使用它们来构建我的UI菜单。为了使导航工作,我将urlhash保存在表中,并将其绑定到锚标记。当您创建路由时,您不必设置hash属性,路由器插件将为您解决这个问题。因此,对于您请求的示例,创建如下菜单集合:

    { displayname: 'Inbox' cssClass: 'icon-inbox', urlHash: '' children[
{ displayname: 'Doc 1' cssClass: 'icon-message', urlHash: 'inbox/viewer/12345' },
{ displayname: 'Doc 2' cssClass: 'icon-message', urlHash: 'inbox/viewer/12346' },
{ displayname: 'File 1' cssClass: 'icon-message', urlHash: 'inbox/viewer/12347' }]}
{ route: 'inbox/viewer/:messageId', moduleId: 'home', title: '', nav: false, cssClass: 'icon-inbox' },
创建如下所示的路线:

    { displayname: 'Inbox' cssClass: 'icon-inbox', urlHash: '' children[
{ displayname: 'Doc 1' cssClass: 'icon-message', urlHash: 'inbox/viewer/12345' },
{ displayname: 'Doc 2' cssClass: 'icon-message', urlHash: 'inbox/viewer/12346' },
{ displayname: 'File 1' cssClass: 'icon-message', urlHash: 'inbox/viewer/12347' }]}
{ route: 'inbox/viewer/:messageId', moduleId: 'home', title: '', nav: false, cssClass: 'icon-inbox' },
有关向管线传递参数的信息,请参见

将此菜单作为可从shell中读取的计算对象公开,并将其绑定到UL/LI菜单html,而不是router.NavigationModel。需要时,使用来自服务器的新数据更改“收件箱”菜单的“子项”属性的内容