amitaibu
amitaibu

Reputation: 1116

Navigation menu in Yesod

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

Answers (2)

amitaibu
amitaibu

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

MarLinn
MarLinn

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

Related Questions