
On Sun, 13 Feb 2011 15:35:48 +0200, Michael Snoyman
On Sun, Feb 13, 2011 at 12:51 PM, Dmitry Kurochkin
wrote: Hello.
I am trying to make a menu widget for a site. It would render list of menu items and mark the active one. I started with a new Menu module that exports (mainMenu :: Widget ()) function. The function gets the current route, iterates over a list of (item title, item route) list and constructs the menu. Now I can import Menu in a handler module and use ^{mainMenu} in hamlet template.
Next I tried to put the menu widget to default layout - menu should be on every page so default layout is where it belongs. Rest of the email describes problems I got.
For the record, I think this is a very good approach. Let's address specific issues below.
Glad to hear :)
1. Module import loop.
I need to import the widget module in the module which defines defaultLayout, i.e. the main application module. But the widget module uses the main application module to have routes and probably other staff, hence import loop. I tried to separate foundation and route declaration from Yesod instance declaration, so that the widget module could import just routes declaration and Yesod instance could import the widget module. Turns out that does not work:
The simplest solution is to just define the mainMenu widget in the same file as the Yesod instance. Is there a reason to avoid this?
Application may have many widgets. They can be pretty complex and big. Each widget is not related to another. I like putting separate things to separate modules, just like handlers for different resources.
It's definitely possible to split up the Yesod instance and the call to mkYesodData, but doing so requires an orphan instance. It's not a particularly *dangerous* orphan instance, but even so I think avoiding orphans is a good goal.
I guess my Haskell and/or Yesod knowlege is not enough to solve this.
Attempting to interpret your app... Compile failed:
Menu.hs:20:23: Couldn't match expected type `Route m' against inferred type `TestAppRoute' NB: `Route' is a type function, and may not be injective In the first argument of `\ u[a7Kv] -> hamlet-0.7.0.2:Text.Hamlet.Quasi.urlToHamletMonad u[a7Kv] []', namely `AboutR' In a stmt of a 'do' expression: \ u[a7Kv] -> hamlet-0.7.0.2:Text.Hamlet.Quasi.urlToHamletMonad u[a7Kv] [] AboutR In the first argument of `hamlet-0.7.0.2:Text.Hamlet.Quasi.toHamletValue', namely `do { (hamlet-0.7.0.2:Text.Hamlet.Quasi.htmlToHamletMonad . preEscapedString) "