Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace Validation_Scratchpad
- open System
- open IntelliFactory.WebSharper
- open IntelliFactory.WebSharper.UI.Next
- open IntelliFactory.WebSharper.UI.Next.Html
- [<JavaScript>]
- module Client =
- // Model-y Stuff Here
- type EMailAddress = EMail of string
- type TelephoneNumber = TN of string
- let showPhone (TN s) = s
- let showEMail (EMail e) = e
- type Person =
- {
- PersonName : string
- PersonEMailAddress : EMailAddress
- PersonTelephoneNumber : TelephoneNumber
- }
- let mkPerson name num email =
- {
- PersonName = name
- PersonEMailAddress = email
- PersonTelephoneNumber = num
- }
- // Define Result sum type
- type ErrorMsg = string
- type Result<'a> = | Success of 'a | Failure of ErrorMsg
- // Helpers
- let txt = Doc.TextNode
- let (==>) attrId attrVal = Attr.Create attrId attrVal
- // Validation: takes num var, produces Result<TelephoneNumber>
- let validateNum vNum =
- View.FromVar vNum
- |> View.Map (fun num ->
- if String.forall Char.IsDigit num && num.Length > 0 then
- TN num |> Success
- else
- Failure "Not a valid telephone number"
- )
- // Same for email
- let validateEmail vEmail =
- View.FromVar vEmail
- |> View.Map (fun (email : string) ->
- if email.Contains("@") then
- EMail email |> Success
- else
- Failure "Not a valid email address"
- )
- // Displays nothing if success, err if failure
- let DisplayFailure = function
- | Success _ -> ""
- | Failure err -> err + ", "
- // View.Do and let! translate to View.Bind, so this updates whenever
- // any of the fields change.
- // We take a View<string> for name, and View<Result<TelephoneNumber>> and
- // View<Result<EmailAddress>> for the validated fields
- // NOTE: This won't compile in W# in the public UI.Next just yet (we forgot a JS tag)
- // but will do on next release
- let PersonView nameView telView emailView =
- View.Do {
- let! name = nameView
- let! tel = telView
- let! email = emailView
- match (tel, email) with
- // If successfully validated for both, we can construct a View<Success<Person>>
- | (Success t, Success e) ->
- return mkPerson name t e |> Success
- | _ ->
- // If not, we concat the errors to get a failure
- // This is the bit I'm not happy about -- would be much nicer to make this more
- // general
- return
- DisplayFailure tel + DisplayFailure email
- |> Failure
- }
- // Person -> Doc
- let showPerson p =
- Div0 [
- P0 [txt <| "Name: " + p.PersonName]
- P0 [txt <| "Phone Number: " + (showPhone p.PersonTelephoneNumber)]
- P0 [txt <| "EMail Address: " + (showEMail p.PersonEMailAddress)]
- ]
- // Result<Person> -> Doc
- let ShowResult personView =
- personView
- |> View.Map (fun personRes ->
- match personRes with
- | Success p -> showPerson p
- | Failure errs -> txt errs
- )
- // Form and main document
- let myForm =
- // Create variables
- let rvName = Var.Create ""
- let rvTel = Var.Create ""
- let rvEmail = Var.Create ""
- Div0 [
- Div0 [
- // Create form controls
- Div0 [
- Html.Label ["for" ==> "nameBox"] [txt "Name:"]
- Doc.Input ["id" ==> "nameBox"] rvName
- ]
- Div0 [
- Html.Label ["for" ==> "telBox"] [txt "Telephone Number:"]
- Doc.Input ["id" ==> "telBox"] rvTel
- ]
- Div0 [
- Html.Label ["for" ==> "emailBox"] [txt "Email:"]
- Doc.Input ["id" ==> "emailBox"] rvEmail
- ]
- ]
- Div0 [
- txt "Result"
- Elements.Br [][]
- // validateNum and validateEmail perform validation on the names and emails,
- // producing View<Result<TelephoneNumber>> and View<Result<EMailAddress>>
- PersonView (View.FromVar rvName) (validateNum rvTel) (validateEmail rvEmail)
- |> ShowResult
- |> Doc.EmbedView
- ]
- ]
- let Main =
- JavaScript.Log("Running JavaScript Entry Point..")
- Doc.RunById "my-container" myForm
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement