Durandaljs从json生成子菜单

时间:2014-05-10 21:38:45

标签: json knockout.js durandal-2.0

好吧,我对durandal很新。我真的在努力实现这一目标。

以下是我要做的事情:主要导航受到收件箱,草稿,提交等的影响。点击这些,为用户提供一个出现在主导航侧面的子菜单。这个子菜单是由我从服务器获取的json数据生成的。单击子菜单中的选项应基于文档的ID在查看器视图模型中打开文档。

实施例

用户点击收件箱 2.菜单出来,包含收件箱中的文件。用户点击视图 3.单击的文档将显示给用户。 所以当他们达到这一点时,我希望网址是mysite.com/#inbox/viewer/123456(123456是文件记录)

我只是找不到与此相似的正常例子,并且想知道是否有人可以帮我指出正确的方向。

我通过将每个主导航链接创建到模块,并在每个模块中都有一个文档窗口来实现它,但我认为必须有更好的方法。所以我要做的是将我的子导航保持在shell中。我不希望每个主要导航项都有一个模块。

这是我现在的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>

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

对于你想要做的事情,听起来好像使用navigationModel是行不通的。根据我的经验,navigationModel和route是1对1的关系。你要做的是让一条路线的参数与多个菜单项相关联。为此,您应该分开菜单和路线。请记住,您只需将javascript对象和集合绑定到html元素即可。 router.navigationModel属性就是这个,它是根据您定义的路由构建的javascript对象的集合。当你调用它正在做的.buildNavigationModel()时,建立一个新的javascript对象集合,你可以绑定到你的菜单html。没有什么能阻止您在shell viewmodel上创建一个全新的属性,该属性包含您自己的javascript菜单对象的自定义集合并将其绑定到您的UL / LI导航html。如果你将这个新的菜单集合作为computedObservable,那么你可以根据需要以懒惰的方式添加它,并且因为它与knockout绑定,所以更改会自动出现在UI中。我已经在许多不同的项目上完成了这项工作并且工作正常。我在后端构建一个菜单表,然后只返回用户有权访问的项目,并使用它来构建我的UI菜单。为了使导航工作,我将urlhash保留在表中并将其绑定到锚标记。当您创建路由时,您不必设置哈希属性,路由器插件将为您处理。因此,对于您请求的示例,请创建如下菜单集:

    { 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' },

有关将参数传递给路径的信息,请参阅durandal docs

将此菜单显示为来自shell的computedObesrvable,并将其绑定到您的UL / LI菜单html而不是router.NavigationModel。需要时,使用服务器中的新数据更改收件箱菜单的children属性的内容。