Capturing Persistent Relations in a Form

2020-04-19 18:54发布

问题:

I have defined a one-to-many relationship in Persistent but could not figure out how to create a form that can take one of the foreign keys as input. Simplifying my use case to something like this:

Person
  name String

Car
  personId PersonId 
  name Text
  type Text

Now when I try to generate a Form for Car, what should be the field type for personId? I tried something like this but get an error:

entryForm :: Maybe Car -> Form Car
entryForm car = renderDivs $ Car
    <$> areq   personIdField   "Person" Nothing
    <*> areq   textField   "Car Name" ( carName <$> car)
    <*> areq   textField  "Type" ( carType <$> car)

When I run the above I get the error: Not in scope: `personIdField'.

I tried intField and it says:

Couldn't match expected type `KeyBackend
                                persistent-1.2.1:Database.Persist.Sql.Types.SqlBackend Person'
            with actual type `Text'
Expected type: Field
                 m0
                 (KeyBackend
                    persistent-1.2.1:Database.Persist.Sql.Types.SqlBackend Person)
  Actual type: Field m0 Text
In the first argument of `areq', namely `intField'
In the second argument of `(<$>)', namely
  `areq intField "Person" Nothing

Ideally I would like to populate a drop down of Person Names (if there are not too many) or have a free form text field (e.g., with autocomplete) when there are too many. Any suggestions on how I can get foreign key as an input from the user?

Update:

I tried using selectField as follows but not sure if I am doing this correctly. I still get an error. First I created a where statement to get personId:

 where
   personId = do  
       person <- runDB $ selectFirst [] [Asc PersonName] 
       case person of
           Just (Entity pId p) -> return pId
           -- Nothing             -> ???

and then I changed my first areq to

 <$> areq (selectField [("First", personId)]) "Person Name" Nothing

Thanks!

回答1:

I was able to figure out how to use selectField properly. This is what I ended up doing:

where
    people = do
        entities <- runDB $ selectList [] [Asc PersonName]
        optionsPairs $ map (\p -> (personName $ entityVal p, entityKey p)) entities

The form field became:

<$> areq   (selectField people) "Person Name" Nothing

I still have not figured out free form entry just yet but this is a good start.



标签: haskell yesod