Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
468 views
in Technique[技术] by (71.8m points)

knockout.js - Durandal Subrouting (Hottowel)

Basically, I am trying to create a menu inside a menu. So, within a main menu route, there will be a vertical menu with another set of routes. When clicking on the submenu routes, only a part of the page gets updated, and the vertical menu does not reload. I am guessing it would be similar to this KO fiddle http://jsfiddle.net/dPCjM/, but there would need to another set of "ghost" KO directives in a main route view:

 <!--ko compose: {model: router.activeItem, 
            afterCompose: router.afterCompose, 
            transition: 'entrance'} -->
 <!--/ko-->

and some other configs on the durandal router...

EDIT: And to clarify, I am not trying to create a dropdown in one of the main menu items. I am trying to create a menu inside one of the views. Basically a durandal app inside a durandal app :)

IFRAMES?? :))))))))))

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

EDIT

As of Durandal.js 2.0 the Router pluggin now has a built in Child Routers which allows for deeplinking out of the box.

/Edit

The below answer perstains to durandal 1.2

The durandal router plugin is a wrapper around sammyjs.

The router plugin allows you to control the browser history stack and also gives your spa the ability to link into pages w/in your spa.

Its pretty easy to get it to do linking 1 level deep where you have 1 main menu and pages that swap in and out. But what if you wanted to have a sub menu w/in the main menu and provide deep linking.

When the router is queued to swap views the viewmodel activator first checks if the request is for the same page in your viewmodel. If it is the same view then you can cancel the route before it happens. By canceling the route when it calls the same page this allows you to take the route parameters and handle the subroute yourself.

The method that checks to see if its calling the same page is in the viewmodel called areSameItem. You can override this method inside your main viewmodel by calling:

return App = {
  router: router,
  subPage: ko.observable('defaultSubPage'),
  activate: function () {
     router.activeItem.settings.areSameItem = function (currentItem, newItem, data) {
        if (currentItem != newItem) { return false; }
        else { App.subPage(convertSplatToModuleId(data.splat)); return true; }
     }
  }
}

Of course this is inside an amd module and router is the durandal router plugin. convertSplatToModuleId is a function that takes the splat property, which is the route values, and converts it to the module of the sub page you wish to show.

So, that part was easy but there is 1 more thing that needs to be done.

<div data-bind="compose: { model: subPage, afterCompose: router.afterCompose }"></div>

Your binding for the container of the subPages needs to call router.afterCompose because this is what tells the router that the route has been completed and its ready to handle new routes.

This is not an easy task to explain. So, I created an example and pushed it to github here.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...