2012-02-08 6 views
0

ユーザーは既存の値リストから選択するか、新しい(テキスト)値を作成するフォームを持っています。フォーム内での複数の入力選択

これをコード化する最もエレガントな方法は何でしょうか?

そうすることの私の最高(およびIMOので、エレガントではない)方法は、定義することによってだった:

data MyInput = MyInput {createNew :: Bool, newVal :: Maybe Text, existingVal :: Maybe Text} 

myForm :: [(Text,Text)] -> Html -> MForm MySite MySite (FormResult MyInput,Widget) 
myForm exisingVals = renderTable $ MyInput 
    <$> areq boolField "Create new" (Just False) 
    <*> aopt textField "New val" Nothing 
    <*> aopt (selectField existingVals) "Existing values" Nothing 

、フォームが受信されると、のようなものを通して結果を渡す:

getMyValue :: MyInput -> Either ErrorMsg Text 
getMyValue i = if createNew i 
        then if newVal i == Nothing || existingVal i /= Nothing 
          then Left "Missing new value or illegal input" 
          else Right . fromJust . newVal $ i 
        else if existingVal i == Nothing || newVal i /= Nothing 
          then Left "Missing selection or illegal input" 
          else Right . fromJust . existingVal $ i 

そして、ハンドラにフォームを再送信するか、結果に応じて続行するかを決定させます。

より良い/短くてよい提案はありますか? 私のリアルフォームには、このような2つの選択/作成フィールドがあり、データ構造と処理がさらに面倒です。 おかげで、

答えて

0

あなたは共通のコード、使用パターンマッチングと警備員を考慮し、アクセサ関数を受け入れ高次機能を一般化することができます

import Control.Arrow ((&&&)) 

getVal isNew newVal oldVal i | isNew i = checkVal "new value" $ (newVal &&& oldVal) i 
          | otherwise = checkVal "selection" $ (oldVal &&& newVal) i 
    where checkVal _ (Just val, Nothing) = Right val 
     checkVal name _    = Left $ "Missing " ++ name ++ " or illegal input" 

getMyVal = getVal createNew newVal existingVal 
+0

おかげで、これは実際にコードクリーナーを作ります。私は、ハンドラでの結果をチェックする必要性を避けるための方法があることを期待していました(これは、Yesodのcheck/checkMを介した単一フィールド入力の場合に可能です)。そうでなければ、おそらくこれが最良の解決策です。 –

関連する問題