Creating Dynamic Navigation Menu

I am using a standard adjacency model for my site navigation. This works well for creating a standard navigation link hierarchy. However, I would now like to be able to mix-in navigation links that would be derived dynamically from a query.

Let me explain a little more. Using the standard schema one create a navigation link such as; categories. That link would than be added to the menu. Now I would like to list all categories below that menu. The only way to do that at this time would be to create a new navigation link under categories for every category. The problem here becomes that true category modification, subtraction or addition will not be pushed to menu. So if one decides to remove a category or change a categories label the associated category navigation link would also need to be managed appropriately.

Instead I would like to be able to bind a query or model callback to navigation link. This would essentially make it possible to retrieve all categories or any other entities deemed necessary at the time the menu is being requested.

The solution that I thus far have thought of for this to work are somewhat contrived so be fair warned. What I was thinking that I could do is create a special navigation link that either stores raw SQL or a datasource call back. When the navigation link is parsed on the application side the SQL or data source method is called and the returned array replaced the navigation link.

This actually works considering the requirement of just getting the links on the menu. The problem becomes sorting. I can’t for the life of me find a good way to mix-in these “dynamic items” with the rest of static menu. The obvious example of were this becomes an issue is when mixing dynamic links with static ones on the same tier of the menu. The primary problem here is that a single navigation link only exists for what could be several dynamic links based on the query or data source binding.

So that got me thinking the only way to reliably do this is to create a pseudo unique id for every item returned by the query or data source binding. This would make it possible to use a separate table with the sorting of all dynamic items. This would also allow newly added items to be placed on the bottom without affecting any that are sorted.

Of course the example I provided with the categories way by example only to understand the the scope of the problem. In the end I would want to integrate this functionality on a generic level were any dynamic entities could be mixed in with static navigation links.

I have yet to come across anything link what I’m describing. Most only support a rigid, static menu hierarchy using the standard parent child relationship. So if anyone has concurred the same problem on a generic level I would appreciate some advice or direction on how to handle everything. The method I presented earlier seems just hackish, though it would get the job done. Perhaps there is a better way?

So just roughing out something here perhaps something like this: (you don’t hve to tell me how contrived this is – I know, better ideas?)


id      |   label           |      parents_id       |          binding          |    dynamics_id            |    pseudo_id
-------------------------------------------------------------------------------------------------------------------------
8       |  Categories       |          0            |          NULL             |       NULL                |    NULL
9       |  NULL             |          8            |  SELECT x id, y label     |       NULL                |    NULL
        |                   |                       |  FROM CATEGORIES          |                           |
12      |  NULL             |          8            |          NULL             |         9                 |     90 (id returned in select)

This way I can map the sort order to data returned by the binding. I can also build out the menu further on the dynamic link because a “record” exists as a place-holder although the actual data is resolved at request time by the binding.