[web-devel] [Yesod] widgets in default layout

Dmitry Kurochkin dmitry.kurochkin at gmail.com
Tue Feb 22 11:08:02 CET 2011


On Mon, 21 Feb 2011 07:23:56 +0200, Michael Snoyman <michael at snoyman.com> wrote:
> On Sun, Feb 20, 2011 at 11:04 PM, Dmitry Kurochkin
> <dmitry.kurochkin at gmail.com> wrote:
> > Hi Michael.
> >
> > On Sun, 13 Feb 2011 19:13:06 +0300, Dmitry Kurochkin <dmitry.kurochkin at gmail.com> wrote:
> >> On Sun, 13 Feb 2011 17:44:33 +0200, Michael Snoyman <michael at snoyman.com> wrote:
> >> > On Sun, Feb 13, 2011 at 5:28 PM, Dmitry Kurochkin
> >> > <dmitry.kurochkin at gmail.com> wrote:
> >> >
> >> > > Still the argument remains. I want to have all menu-related code in a
> >> > > separate module.
> >> >
> >> > OK. As I said, this is possible, and it sounds like you already got
> >> > 90% of the way there. I don't know what's holding you up until I see
> >> > your code. My initial reaction is still that this is a bad idea in
> >> > general, though I *am* reconsidering that position. It might make
> >> > sense to alter the approach used by the scaffolded site.
> >> >
> >>
> >> I will try to send you some an example later. Unfortunately, I do not
> >> have time for this right now. Playing with Yesod in my free time only.
> >>
> >
> > I took another look at it. Turns out my problem was caused by using
> > getCurrentRoute in the widget. If there is no getCurrentRoute, it works
> > fine and I can use the widget in the defaultLayout.
> >
> > Here is a simple code to demonstrate the issue:
> >
> >    testWidget :: GWidget sub Test ()
> >    testWidget = do
> >        Just route <- lift getCurrentRoute
> >        addWidget [$hamlet|@{route}|]
> >
> > Add the above code to the main application module. In the above case
> > Test is the foundation type. I get the following error:
> >
> >    Couldn't match expected type `TestRoute'
> >           against inferred type `Route sub'
> >      NB: `Route' is a type function, and may not be injective
> >
> > I would appreciate if you explain what the problem is and how to solve
> > it.
> 
> getCurrentRoute[1] returns a route for the current subsite, while you
> want a route for Test (ie, Route sub vs Route Test). You need to
> convert your Route sub into a Route Test, by using
> getRouteToMaster[2].
> 

Thank you! The following works:

    testWidget :: GWidget sub Test ()
    testWidget = do
        Just route <- lift getCurrentRoute
        routeToMaster <- lift getRouteToMaster
        addWidget [$hamlet|@{routeToMaster route}|]

Perhaps a getCurrentMasterRoute function would be useful? Though I am
not sure how common is my case.

So look like the only real issue with putting widgets for defaultLayout
to a separate module is separating mkYesodData and Yesod instance. You
were talking about orphan Yesod instance, is it some kind of dummy
instance declaration that would allow widgets to use Yesod instance
without importing the actual module that defines it?

Regards,
  Dmitry

> Michael
> 
> [1] http://hackage.haskell.org/packages/archive/yesod-core/0.7.0.1/doc/html/Yesod-Handler.html#v:getCurrentRoute
> [2] http://hackage.haskell.org/packages/archive/yesod-core/0.7.0.1/doc/html/Yesod-Handler.html#v:getRouteToMaster



More information about the web-devel mailing list