Last active
January 8, 2018 22:49
-
-
Save WolfDan/5d4e7f3c7d994b1b0a3bb4e4c6f07d66 to your computer and use it in GitHub Desktop.
ReForm validation proposal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Source from: https://github.com/Astrocoders/reform I edited it to handle the onChange events and validation */ | |
type action = | |
| HandleChange((string, string)) | |
| HandleSubmit; | |
type validation = | |
| Required | |
| MinLength(int) | |
| MaxLength(int) | |
| Between(int, int) | |
| SameAs(string) | |
| Regex(string) | |
| Alpha | |
| AlphaNum | |
| Numeric | |
| Url; | |
let validate = (validation, value) => | |
switch validation { | |
| Required => value === "" | |
| MinLength(length) => String.length(value) < length | |
| MaxLength(length) => String.length(value) > length | |
| Between(min, max) => String.length(value) < min || String.length(value) > max | |
| SameAs(same_value) => value != same_value | |
| Regex(regex) => Js.Re.test(value, Js.Re.fromString(regex)) | |
| Alpha => ! Js.Re.test(value, [%bs.re "/^[a-zA-Z]*$/"]) | |
| AlphaNum => ! Js.Re.test(value, [%bs.re "/^[a-zA-Z0-9]*$/"]) | |
| Numeric => ! Js.Re.test(value, [%bs.re "/^[0-9]*$/"]) | |
| Email => ! Js.Re.test(value, [%bs.re "/@/"]) | |
| Url => | |
! | |
Js.Re.test( | |
value, | |
[%bs.re | |
"/^(?:(?:https?|ftp):\\/\\/)(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:[/?#]\\S*)?$/" | |
] | |
) | |
}; | |
let doValidation = (validationList, value) => | |
validationList |> List.filter((validation) => validate(validation, value)); | |
module Create = | |
( | |
Config: { | |
type state; | |
let handleChange: (action, state) => state; | |
let initialState: state; | |
let getValidation: (string, state) => (list(validation), string); | |
} | |
) => { | |
type values = Config.state; | |
type state = {values}; | |
let component = ReasonReact.reducerComponent("ReForm"); | |
let make = (~onSubmit: values => unit, ~validate: list(string), children) => { | |
...component, | |
initialState: () => {values: Config.initialState}, | |
reducer: (action, state) => | |
switch action { | |
| HandleChange((_, _)) => | |
ReasonReact.Update({values: Config.handleChange(action, state.values)}) | |
| HandleSubmit => | |
onSubmit(state.values); | |
ReasonReact.NoUpdate | |
}, | |
render: (self) => { | |
let handleChange = (field) => | |
self.reduce( | |
(event) => | |
HandleChange(( | |
field, | |
ReactDOMRe.domElementToObj(ReactEventRe.Form.target(event))##value | |
)) | |
); | |
let handleFormSubmit = self.reduce((_) => HandleSubmit); | |
let isValid = (field: string) => { | |
let (validationList, fieldValue) = Config.getValidation(field, self.state.values); | |
doValidation(validationList, fieldValue) | |
}; | |
let handleSubmit = (_) => { | |
let validationError = validate |> List.map((field) => isValid(field)) |> List.flatten; | |
validationError == [] ? handleFormSubmit() : ignore() | |
}; | |
children(~form=self.state, ~handleChange, ~handleSubmit, ~isValid) | |
} | |
}; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open ReactRouter; | |
open ReForm; | |
let text = ReasonReact.stringToElement; | |
module SignInFormParams = { | |
type state = { | |
password: string, | |
password_confirmation: string, | |
email: string | |
}; | |
let initialState = {password: "", email: "", password_confirmation: ""}; | |
let handleChange = (action, state) => | |
switch action { | |
| HandleChange(("password", value)) => {...state, password: value} | |
| HandleChange(("email", value)) => {...state, email: value} | |
| HandleChange(("password_confirmation", value)) => {...state, password_confirmation: value} | |
| _ => state | |
}; | |
let getValidation = (field, state) => | |
switch field { | |
| "password" => ([Required, Between(8, 15)], state.password) | |
| "password_confirmation" => ([SameAs(state.password)], state.password_confirmation) | |
| "email" => ([Email, Required], state.email) | |
| _ => ([], "") | |
}; | |
}; | |
let showError = (error) => | |
switch error { | |
| Required => "The field is required" | |
| Between(min, max) => | |
"Name must have at least " | |
++ string_of_int(min) | |
++ " and less than " | |
++ string_of_int(max) | |
++ "letters" | |
| Email => "The given email is invalid" | |
| SameAs(_value) => "The given value aren't equal" | |
| _ => "What ever" | |
}; | |
module ReForm = ReForm.Create(SignInFormParams); | |
let component = ReasonReact.statelessComponent("Register"); | |
let make = (_children) => { | |
...component, | |
render: (_self) => { | |
let validate: list(string) = ["password", "password_confirmation", "email"]; | |
let signInMutation: SignInFormParams.state => unit = (values) => Js.log(values); | |
<div className="grid-full-background"> | |
<div className="main-nav"> <NavBar navClassName="content" /> </div> | |
<div className="background-container"> | |
<div className="background" /> | |
<div className="form-auth"> | |
<div className="title-section"> | |
<h1 className="title auth"> (text("Welcome")) </h1> | |
<span className="subtitle auth"> (text("Register and join the community")) </span> | |
</div> | |
<ReForm onSubmit=signInMutation validate> | |
...( | |
(~form, ~handleChange, ~handleSubmit, ~isValid) => | |
<Form> | |
<label> | |
(text("Email")) | |
<input | |
_type="email" | |
value=form.values.email | |
onChange=(handleChange("email")) | |
/> | |
( | |
ReasonReact.arrayToElement( | |
Array.map( | |
(error) => text(showError(error)), | |
Array.of_list(isValid("email")) | |
) | |
) | |
) | |
</label> | |
<label> | |
(text("Password")) | |
<input | |
_type="password" | |
value=form.values.password | |
onChange=(handleChange("password")) | |
/> | |
( | |
ReasonReact.arrayToElement( | |
Array.map( | |
(error) => text(showError(error)), | |
Array.of_list(isValid("password")) | |
) | |
) | |
) | |
</label> | |
<label> | |
(text("Password Confirmation")) | |
<input | |
_type="password" | |
value=form.values.password_confirmation | |
onChange=(handleChange("password_confirmation")) | |
/> | |
( | |
ReasonReact.arrayToElement( | |
Array.map( | |
(error) => text(showError(error)), | |
Array.of_list(isValid("password_confirmation")) | |
) | |
) | |
) | |
</label> | |
<button className="button primary full" onClick=handleSubmit> | |
(text("Sign Up")) | |
</button> | |
</Form> | |
) | |
</ReForm> | |
<div className="additional-section"> | |
<span> (text("Already have an account? ")) </span> | |
<Link _to="/account/login"> (text("Login here")) </Link> | |
</div> | |
</div> | |
</div> | |
</div> | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment