Reputation: 1116
I'm looking at implementing a menu (something like this). What is the right way to do it? I didn't find any examples in Yesod itself, nor other libraries that do it.
Upvotes: 0
Views: 196
Reputation: 1116
Here is a simplified example of what I've ended up with:
-- Foundation.hs
data MenuItem = MenuItem
{ _menuItemLabel :: Text
, _menuItemRoute :: Route App
, _menuItemAccessCallback :: Bool
} deriving (Show)
instance Yesod App where
-- ...
defaultLayout widget = do
-- ...
muser <- maybeAuthPair
mcurr <- getCurrentRoute
-- All the menu items.
let menuItems =
[ MenuItem
{ _menuItemLabel = "Home"
, _menuItemRoute = HomeR
-- Always show menu item.
, _menuItemAccessCallback = True
}
, MenuItem
{ _menuItemLabel = "People"
, _menuItemRoute = PeopleR
-- Example for item that shows only if user is authenticated.
, _menuItemAccessCallback = isJust muser
}
]
-- Filter items to show only accessible items
let filteredMenuItems = [x | x <- menuItems, _menuItemAccessCallback x == True]
And inside the default template file:
-- default-layout.hamlet
<nav>
$forall MenuItem label route _ <- filteredMenuItems
<a class="item" :Just route == mcurr:.active href="@{route}">#{label}
Upvotes: 0
Reputation: 319
The problem description sounds like something I would mostly handle on the client-side with js and possibly ajax or even with form elements + clever css.
I assume most sites that are built with Yesod these days don't have more than maybe a half dozen navigation entries so a separate subsystem just for menues wasn't something many people needed. But maybe I overlooked something, so take a look yourself.
That being said, it should be relatively simple to develop your own subsystem if you really need it. After all, all you need is for some little piece of hamlet to change based on an enum or something.
Upvotes: 1