reform validation of dependent fields

23 views
Skip to first unread message

Richard Wallace

unread,
Nov 8, 2012, 12:57:09 AM11/8/12
to ha...@googlegroups.com
Hello,

Today I have a question on how to do validation when some fields depend on the value of others.  For instance, take the simple example of a signup or change password form, where you have 2 password fields, both of which must be non-empty and have the same value.

Or, as a more complicated example, say you have a form with a <select> element and based on the users selection, some fields may become required, optional, or even forbidden.

Is there a good way to represent this kind of field value dependent validation in reform?  I can't see any obvious way, the proof system is cool, but seems limited to just inspecting the value of a one field at a time.

Thanks,
Rich

Jeremy Shaw

unread,
Nov 8, 2012, 11:16:46 AM11/8/12
to HAppS
reform does not validate fields, it validates forms. And forms are built by combining other forms together. At the bottom we have a bunch of forms that contain only one field such as inputText, select, textarea, etc. 

For something like confirming a password, we can create a form like this:

      password :: AuthForm v Text
      password =
          errorList ++> (((,) <$> password1 <*> password2) `transformEither` samePassword) `transformEither` minLength 6

That will create a form with two password fields. Then it uses transformEither to confirm that both fields are the same, and if so, returns their value, otherwise it returns a validation error. It also checks that the password is at least 6 characters long. That password form can then be used in the overall account create form. Here is the complete example:

newAccountForm :: (Functor v, MonadIO v) => AcidState AuthState -> AuthForm v (AuthId, UserPassId)
newAccountForm authStateH =
    (R.fieldset
     (errorList ++>
      (R.ol $ (((,) <$> username <*> password <* submitButton)))
                    `transformEitherM`
                    createAccount))
    where
      submitButton = R.li $ (mapView (\html -> html ! A.class_  "submit") $ inputSubmit "Create Account")
      username  = R.li $ errorList ++> ((label ("username: " :: String)       ++> inputText mempty) `transformEither` (minLength 1))
      password1 = R.li $ label ("password: " :: String)         ++> inputPassword
      password2 = R.li $ label ("confirm password: " :: String) ++> inputPassword

      password =
          errorList ++> (((,) <$> password1 <*> password2) `transformEither` samePassword) `transformEither` minLength 6

      samePassword (p1, p2) =
              if p1 /= p2
               then (Left $ PasswordMismatch)
               else (Right p1)

      createAccount (username, password) =
              do passHash <- liftIO $ mkHashedPass password
                 r <- update' authStateH $ CreateUserPass (UserName username) passHash
                 -- fixme: race condition
                 case r of
                   (Left e) -> return (Left $ UPE e)
                   (Right userPass) ->
                       do authId <- update' authStateH (NewAuthMethod (AuthUserPassId (upId userPass)))
                          return (Right (authId, upId userPass))

The <select> variation is a bit trickier. There is no reason why the validation can not be done correctly on the server-side, but for a system like that, it seems like you might also want to have some clientside actions happening. For example, disabling/hiding the 'forbidden' actions via javascript.

Right now that would require you to manually attach an onchange handler to the select element to enable/disable other fields. Which is possible.. just not elegant.

reform (and similar libraries) are great for web 1.0. Making things more web 2.0 is still largely unexplored. Though I am hoping that things like Fay will open the doors to making things like client-side validation easier.

- jeremy


--
You received this message because you are subscribed to the Google Groups "HAppS" group.
To post to this group, send email to ha...@googlegroups.com.
To unsubscribe from this group, send email to happs+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/happs?hl=en.

Richard Wallace

unread,
Nov 9, 2012, 11:33:39 AM11/9/12
to ha...@googlegroups.com
Thanks Jeremy, obviously I need to spend more time looking at the various combinators in reform and figuring out how to combine them for great good.

Appreciate the help.

Rich
Reply all
Reply to author
Forward
0 new messages