Created
March 9, 2018 17:36
-
-
Save bijancn/05f67168cb8aa3b0c5f3e8321633fc74 to your computer and use it in GitHub Desktop.
This file contains 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
package client | |
import chandu0101.scalajs.react.components.elementalui._ | |
import japgolly.scalajs.react.component.Scala.Unmounted | |
import japgolly.scalajs.react.vdom.html_<^._ | |
import japgolly.scalajs.react.{ BackendScope, Callback, ReactEventFromInput, ScalaComponent } | |
import scala.scalajs.js | |
import scala.scalajs.js.`|` | |
object ValidatedFormComponent { | |
/** | |
* | |
* @param title the title is used as label for the input HTML | |
* @param typeOfInput the type tag of the input HTML | |
* @param validationDescription the description of the validation to be shown to the user | |
* @param validationFunc the validation function that should be applied to the input value. | |
* @param onChange the function to call on change of the input value. Use this to save changes to your state. | |
* @param value the initial value to render | |
* @param onValidationChange you can supply a function that returns a Callback based on the validation result | |
*/ | |
final case class Props( | |
title: String, | |
typeOfInput: String, | |
validationDescription: String, | |
validationFunc: String => Option[Boolean], | |
onChange: String => Option[Callback], | |
value: js.UndefOr[String | Int], | |
onValidationChange: Option[Boolean => Callback] = None | |
) | |
final case class State( | |
isValid: Boolean | |
) | |
final class Backend(scope: BackendScope[Props, State]) { | |
private def onInputChange(props: Props): ReactEventFromInput => Callback = { | |
event => | |
{ | |
val isValid = props.validationFunc(event.target.value.toString).getOrElse(false) | |
val callback = props.onChange(event.target.value).foldLeft(scope.setState(State(isValid))) { | |
case (setState, onChange) => setState >> onChange | |
} | |
props.onValidationChange.map(f => f(isValid)).foldLeft(callback) { | |
case (cb, fIsValid) => cb >> fIsValid | |
} | |
} | |
} | |
def render(props: Props, state: State): VdomElement = { | |
<.div( | |
FormField(label = props.title)( | |
FormInput( | |
label = props.title, | |
`type` = props.typeOfInput, | |
name = if (!state.isValid) "error" else "", | |
className = if (!state.isValid) "error" else "", | |
value = props.value, | |
autoFocus = true, | |
placeholder = props.validationDescription, | |
multiline = false, | |
required = true, | |
onChange = onInputChange(props) | |
)() | |
)(), | |
<.div( | |
^.className := "formerror", | |
if (!state.isValid) { | |
props.validationDescription | |
} else { | |
"" | |
} | |
) | |
) | |
} | |
} | |
private val component = ScalaComponent | |
.builder[Props]("ValidatedFormComponent") | |
.initialState(State(isValid = true)) | |
.renderBackend[Backend] | |
.build | |
def apply(props: Props): Unmounted[Props, State, Backend] = component(props) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment