简体   繁体   中英

How do I solve “HTTP request failed with: when is not a field” runtime errors in digestive-functors code?

I have a simple and incomplete Happstack application, that consists of a digestive-functors form defined as follows:

setRecFormSpec :: Monad m => Form Text m Reminder
setRecFormSpec = Reminder
    <$> "progname" .: string Nothing
    <*> "channel" .: string Nothing
    <*> "when" .: localTimeFormlet "%d/%m/%Y" "%H:%M" Nothing
    <*> "recordLimit" .: stringRead "Can't parse number" (Just 7)

and its view defined as follows:

setRecView :: View H.Html -> H.Html
setRecView view = do
        H.div ! A.class_ "container" $ do
            H.h1 "Set Record Reminder"
            childErrorList "" view

            divFormGroup $ do
                label "progname" view "Program Name:"
                formControl $ inputText "progname" view

            divFormGroup $ do
                label "channel" view "Channel:"
                formControl $ inputText "channel" view

            divFormGroup $ do
                label "when" view "When:"
                formControl $ inputDate "when" view

            divFormGroup $ do
                label "recordLimit" view "Recording Limit (days):"
                formControl $ inputText "recordLimit" view

            divFormGroup $ do
                formControl $ inputSubmit "Signup"

-- divFormGroup -- candidate to go into a Bootstrap library
divFormGroup :: H.Html -> H.Html
divFormGroup h =
    H.div ! A.class_ "form-group" $ h

-- formControl -- candidate to go into a Bootstrap library
formControl :: H.Html -> H.Html
formControl h = (h ! A.class_ "form-control")

Reminder is defined as follows:

data Reminder = Reminder {
        programName     :: String    -- ^ name of program
    ,   channel         :: String    -- ^ name of broadcast channel
    ,   firstShowing    :: LocalTime  -- ^ time of first showing
    ,   timerPeriodDays :: Integer     -- ^ how far in advance we can set timer, in days
} deriving (Show)

When I browse to the path for the form (/setrec) I get a blank page with the following error message printed on the console:

HTTP request failed with: when is not a field

I've found where that error message is defined (in https://github.com/jaspervdj/digestive-functors/blob/7e50d5686abc4b39389ed195693660d758987c7c/digestive-functors/src/Text/Digestive/Form/Internal.hs ) but I can't see from there why the 'when' field would not be found.

What is the problem here?

How do I debug this kind of issue?

Here's a link to the whole code on github, in case you need to look more deeply at the code:

https://github.com/nmbooker/recremind

I ran into the same error when I used utcTimeFormlet , which internally calls localTimeFormlet so it is likely that this is the same error you experienced.

Take a look at the code of localTimeFormlet

localTimeFormlet dFmt tFmt d = LocalTime
  <$> "date" .: dateFormlet dFmt (localDay <$> d)
  <*> "time" .: timeFormlet tFmt (localTimeOfDay <$> d)

As you can see it consists of two subFormlets, which is the reason why "when" is not a field. It refers to the overall construct with "date" and "time" being the actual fields.

The "solution" I used was to skip this function entirely since I actually only needed a date, not a precise time. If that's the same in your case you probably want to do so, too.

Otherwise you will have to incorporate the two fields into your view and it should work.

I solved it, with a variation on Pseudoradius' solution.

I defined a new view thus:

dateTimeView view = do
    divFormGroup $ do
        label "date" view "When (Date):"
        formControl $ inputText "date" view

    divFormGroup $ do
        label "time" view "When (Time):"
        formControl $ inputText "time" view

and in my form I used it with subView , thus:

setRecView :: View H.Html -> H.Html
setRecView view = do
        H.div ! A.class_ "container" $ do
            -- ...

            divFormGroup $ do
                label "channel" view "Channel:"
                formControl $ inputText "channel" view

            dateTimeView $ subView "when" view

            divFormGroup $ do
                label "recordLimit" view "Recording Limit (days):"
                formControl $ inputText "recordLimit" view

            divFormGroup $ do
                formControl $ inputSubmit "Signup"

Then the runForm call was able to find the when field and get the date and time from it.

I could parameterise dateTimeView with dateLabelText and timeLabelText, and probably will, but the above should be enough for illustrative purposes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM