Skip to content

Instantly share code, notes, and snippets.

@marcpalmer
Created August 31, 2011 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcpalmer/1183594 to your computer and use it in GitHub Desktop.
Save marcpalmer/1183594 to your computer and use it in GitHub Desktop.
Navigation API thoughts

Navigation API

Site navigation is a combination of two concerns - declaring what navigation items there are in the site, and what the structure of them is - as presented to the use.

Specifying items and structure separately is not DRY, and applications also need to have the ability to change the structure to suit them - therefore the structure information provided by a plugin is merely a guide, and inherently disposable.

DSL

A Navigation artefact is used to define navigation items, positioned in their default structure. By combining these two different categories data, we end up with a more DRY approach:

navigation = {
    // Everything here is under "user" in the structure
    user {
        // This defines the "<pluginName>.logout" item
        logout {
            // url is string or g.createLink map
            url controller:'sec', action:'logout'
            isVisible { ... }
            isEnabled { ... }
        }
        login {
            uri controller:'sec', action:'login'
            isVisible { ... }
            isEnabled { ... }
        }
    }
}

Items are specified in a default structure (i.e. user > logout) that the application can override, and ordering is implied. Unique id of each item is the endpoint name in the DSL i.e. "logout" prefixed with the plugin name i.e. "security.logout"

Sub items are supported:

navigation = {
    mail {
        url controller:'mail'
        isVisible { ... }
        isEnabled { ... }
    
        subItems {
            inbox {
                url action:'inbox'
            }
            archive {
                url action:'archive'
            }
        }
    }
}

Here the controller is inherited by subitems. The subitems have implicit ids of "pluginName.inbox" etc.

The subItems clause is merely a way to express the default placement of these items and gain some inheritance of values from the "parent" item, the application can re-structure them.

The text for items is resolved using i18n messages based on the id of the navigation entry (not its placement in the structured).

Application menu re-structuring/re-ordering

Applications need to be able to re-organise menu items into the structure and ordering they desire.

This is done through configuration (or DSL with empty entries?):

grails {
    navigation {
        user = ['security.login', 'security.logout']
        admin = ['admin-home', 'admin-advanced', 'security.logout']
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment