Skip to content

Instantly share code, notes, and snippets.

@bijancn
Created March 9, 2018 17:36
Show Gist options
  • Save bijancn/05f67168cb8aa3b0c5f3e8321633fc74 to your computer and use it in GitHub Desktop.
Save bijancn/05f67168cb8aa3b0c5f3e8321633fc74 to your computer and use it in GitHub Desktop.
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