【问题标题】:Durandaljs generating sub menu from jsonDurandaljs 从 json 生成子菜单
【发布时间】:2014-05-12 20:07:23
【问题描述】:

好吧,我对 durandal 还很陌生。我真的很难做到这一点。

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

例如

用户点击收件箱 2. 菜单出来了,里面有他们收件箱里的文件。用户点击查看 3.被点击的文档显示给用户。 4. 所以当他们到达这一点时,我希望 url 是 mysite.com/#inbox/viewer/123456(123456 是 documentid)

我只是无法找到与此类似的体面示例,并且想知道是否有人可以帮助我指出正确的方向。

我通过使每个主导航链接到一个模块来做到这一点,并在每个模块中都有一个文档窗口,但我认为必须有更好的方法。所以我想要做的是将我的子导航保留在 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>

感谢您的帮助

【问题讨论】:

    标签: json knockout.js durandal-2.0


    【解决方案1】:

    对于您正在尝试做的事情,听起来好像使用 navigationModel 是行不通的。根据我的经验,navigationModel 和 route 是一对一的关系。您要做的是有一条路线,其参数与多个菜单项相关联。为此,您应该将菜单和路线分开。请记住,您只是将 javascript 对象和集合绑定到 html 元素。 router.navigationModel 属性就是这样,从您定义的路由构建的 javascript 对象的集合。当您调用 .buildNavigationModel() 时,它正在执行此操作,构建一个新的 javascript 对象集合,以便您绑定到菜单 html。没有什么可以阻止您在 shell 视图模型上创建一个全新的属性,该属性包含您自己的自定义 javascript 菜单对象集合并将其绑定到您的 UL/LI 导航 html。如果您将这个新菜单集合设置为 computedObservable,您可以根据需要以惰性方式添加到它,并且由于它与敲除绑定,更改将自动出现在 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 属性的内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-22
      • 2012-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多