Skip to content

Commit 72df705

Browse files
committed
re-enabled FormLayout.onChange callback hook -- accidentally disabled it
1 parent b78e318 commit 72df705

File tree

2 files changed

+35
-17
lines changed

2 files changed

+35
-17
lines changed

core/src/main/scala/torstenrudolf/scalajs/react/formbinder/Form.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ case class FormFieldDescriptor[T](descr: (FormFieldArgs[T]) => ReactNode)
6060

6161
abstract class FormLayout[T] {
6262

63-
def onChange(validatedData: Option[T],
64-
allFieldValidationResults: List[ValidationResult],
65-
globalFormValidationResult: ValidationResult): Callback = Callback.empty
63+
// a hook if you need to react on form changes
64+
// this gets triggered every time a field's unvalidated value changes
65+
def onChange(validatedData: Option[T]): Callback = Callback.empty
6666

6767
}

core/src/main/scala/torstenrudolf/scalajs/react/formbinder/Macros.scala

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package torstenrudolf.scalajs.react.formbinder
22

3-
import japgolly.scalajs.react.{BackendScope, Callback, ReactComponentB, ReactNode}
3+
import japgolly.scalajs.react.{BackendScope, Callback, CallbackTo, ReactComponentB, ReactNode}
44
import japgolly.scalajs.react.vdom.prefix_<^._
55

66
import scala.scalajs.js
@@ -222,17 +222,13 @@ object FormField {
222222
validator: (O) => ValidationResult,
223223
parentForm: Form[_] with FormAPI[_])
224224

225-
case class State[O](currentValidationResult: ValidationResult = ValidationResult.Success,
225+
case class State[O](currentValidationResult: Option[ValidationResult] = None,
226226
currentRawValue: Option[O] = None,
227-
showUnitializedError: Boolean = false) {
228-
val currentValidatedValue: Option[O] = if (currentValidationResult.isValid) currentRawValue else None
229-
}
227+
showUnitializedError: Boolean = false)
230228

231229
class Backend[O]($: BackendScope[Props[O], State[O]]) {
232-
// def update(currentValidatedValue: Option[O], currentValidationResult: ValidationResult) =
233-
// $.setState(State(currentValidatedValue = currentValidatedValue, currentValidationResult = currentValidationResult))
234230

235-
def validate(showUnitializedError: Boolean = false): Callback = $.state.zip($.props) >>= { case (state, props) =>
231+
def validate(showUnitializedError: Boolean = false): CallbackTo[ValidationResult] = $.state.zip($.props) >>= { case (state, props) =>
236232
val showUnitializedErrorX = showUnitializedError || state.showUnitializedError
237233
val valueToValidate =
238234
if (showUnitializedErrorX && state.currentRawValue.isEmpty && props.valueIsString) {
@@ -247,11 +243,11 @@ object FormField {
247243
case None => ValidationResult.Success
248244
}
249245

250-
$.modState(_.copy(currentValidationResult = validationResult, showUnitializedError = showUnitializedErrorX))
246+
$.modState(_.copy(currentValidationResult = Some(validationResult), showUnitializedError = showUnitializedErrorX)) >> CallbackTo(validationResult)
251247
}
252248

253249
private def onChangeCB: Callback =
254-
$.state.zip($.props) >>= { case (state, props) => props.onChangeCB(state.currentValidatedValue) }
250+
$.state.zip($.props) >>= { case (state, props) => props.onChangeCB(currentValidatedValue) }
255251

256252
def updateRawValue(v: Option[O]): Callback = {
257253
$.modState(_.copy(currentRawValue = v), cb = validate() >> onChangeCB)
@@ -261,13 +257,20 @@ object FormField {
261257

262258
def resetToDefault: Callback = $.modState(_.copy(showUnitializedError = false), cb = {$.props >>= { props => updateRawValue(props.defaultValue) }})
263259

264-
def currentValidatedValue: Option[O] = $.state.runNow().currentValidatedValue
260+
def currentValidatedValue: Option[O] = {
261+
if (currentValidationResult.isValid) $.state.runNow().currentRawValue else None
262+
}
263+
264+
def currentValidationResult: ValidationResult = $.state.runNow().currentValidationResult match {
265+
case None => validate().runNow()
266+
case Some(vr) => vr
267+
}
265268

266269
def render(props: Props[O], state: State[O]) = <.div(
267270
props.formFieldDescriptor.descr(
268271
FormFieldArgs[O](
269272
currentValue = state.currentRawValue,
270-
currentValidationResult = state.currentValidationResult,
273+
currentValidationResult = currentValidationResult,
271274
onChangeCB = (v: O) => updateRawValue(Some(v)),
272275
resetToDefaultCB = resetToDefault,
273276
clearCB = clear,
@@ -312,7 +315,9 @@ case class FormFieldBinding[O](formFieldDescriptor: FormFieldDescriptor[O],
312315

313316
def currentValidatedValue: Option[O] = formFieldBackend.flatMap(_.currentValidatedValue)
314317

315-
def validate(showUninitializedError: Boolean): Try[Callback] = Try(formFieldBackend.get.validate(showUninitializedError))
318+
def currentValidationResult: Try[ValidationResult] = Try(formFieldBackend.get.currentValidationResult)
319+
320+
def validate(showUninitializedError: Boolean): Try[Callback] = Try(formFieldBackend.get.validate(showUninitializedError).void)
316321

317322
def updateValue(v: O): Try[Callback] = Try(formFieldBackend.get.updateRawValue(Some(v)))
318323

@@ -347,6 +352,11 @@ trait FormAPI[T] extends Form[T] {
347352
private var _validatedFormData: Option[T] = None
348353
private var _formGlobalValidationResult: Option[ValidationResult] = None
349354

355+
private def formGlobalValidationResult: ValidationResult = _formGlobalValidationResult match {
356+
case Some(vr) => vr
357+
case None => throw FormUninitialized
358+
}
359+
350360
protected def globalValidator(data: T): ValidationResult
351361

352362
protected def currentUnvalidated: scala.util.Try[T]
@@ -379,14 +389,22 @@ trait FormAPI[T] extends Form[T] {
379389
override def fullValidate: Callback = Callback {validate(showUninitializedError = true)}
380390

381391
def onChangeCB: Callback = {
382-
Callback(validate(showUninitializedError = false)) >> forceGlobalValidationMessageUpdate.getOrElse(Callback.empty)
392+
Callback(validate(showUninitializedError = false)) >>
393+
forceGlobalValidationMessageUpdate.getOrElse(Callback.empty) >>
394+
formLayout.onChange(validatedData = _validatedFormData)
383395
}
384396

385397
override def validatedFormData: Option[T] = {
386398
validate(showUninitializedError = true)
387399
_validatedFormData
388400
}
389401

402+
private def allFieldValidationResults: List[ValidationResult] = allFormFieldBindings.map(
403+
_.currentValidationResult match {
404+
case Success(vr) => vr
405+
case _ => throw FormUninitialized
406+
})
407+
390408
protected def allFormFieldBindings: List[FormFieldBinding[_]]
391409

392410
override def field[A](fd: torstenrudolf.scalajs.react.formbinder.FormFieldDescriptor[A]): ReactNode =

0 commit comments

Comments
 (0)