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

Michael Snoyman michael at snoyman.com
Tue Feb 22 16:27:03 CET 2011


On Tue, Feb 22, 2011 at 12:08 PM, Dmitry Kurochkin
<dmitry.kurochkin at gmail.com> wrote:
> 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.

If you look through Yesod.Handler, there are a number of functions
that are duplicated for sub and master sites. I had to choose which
one would get the shorter name, and made a call based on my
information at the time. However, I've wondered many times if I made
the wrong choice on some of them. I think it would be a good idea to
revisit all of those decisions before the 1.0 release: making those
changes *will* break code, but not in any significant way. This would
probably be a good candidate for change.

> 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?

Nothing magical, it *should* be possible to just move the Yesod
instance into a separate module. However, you'll likely get a cascade
of error messages which you will need to fix by either moving code
around or changing the type signature to work for any instance of
Yesod. Plus you'll need to make sure that all your handler code
imports that separate module.

In other words: you can achieve this, but you'll be going into
slightly uncharted territory. I give no guarantees that it won't make
your code worse.

Michael

> 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