* Runs validation rules recursively while collecting dependencies allowing for * cross-node validation rules that automatically re-trigger when a foreign * value is changed. * @param current - The index of the current validation rule * @param validations - The remaining validation rule stack to
( current: number, validations: FormKitValidation[], state: FormKitValidationState, removeImmediately: boolean, complete: () => void )
| 286 | * @returns |
| 287 | */ |
| 288 | function run( |
| 289 | current: number, |
| 290 | validations: FormKitValidation[], |
| 291 | state: FormKitValidationState, |
| 292 | removeImmediately: boolean, |
| 293 | complete: () => void |
| 294 | ): void { |
| 295 | const validation = validations[current] |
| 296 | if (!validation) return complete() |
| 297 | const node = validation.observer |
| 298 | if (isKilled(node)) return |
| 299 | const currentRun = state.input |
| 300 | validation.state = null |
| 301 | |
| 302 | function next(async: boolean, result: boolean | null): void { |
| 303 | if (state.input !== currentRun) return |
| 304 | state.isPassing = state.isPassing && !!result |
| 305 | validation.queued = false |
| 306 | const newDeps = node.stopObserve() |
| 307 | const diff = diffDeps(validation.deps, newDeps) |
| 308 | applyListeners( |
| 309 | node, |
| 310 | diff, |
| 311 | function revalidate() { |
| 312 | // Event callback for when the deps change: |
| 313 | try { |
| 314 | node.store.set(validatingMessage) |
| 315 | } catch (e) {} |
| 316 | validation.queued = true |
| 317 | if (state.rerun) clearTimeout(state.rerun) |
| 318 | state.rerun = setTimeout( |
| 319 | validate, |
| 320 | 0, |
| 321 | node, |
| 322 | validations, |
| 323 | state |
| 324 | ) as unknown as number |
| 325 | }, |
| 326 | 'unshift' // We want these listeners to run before other events are emitted so the 'state.validating' will be reliable. |
| 327 | ) |
| 328 | validation.deps = newDeps |
| 329 | |
| 330 | validation.state = result |
| 331 | if (result === false) { |
| 332 | createFailedMessage(validation, removeImmediately || async) |
| 333 | } else { |
| 334 | removeMessage(validation) |
| 335 | } |
| 336 | if (validations.length > current + 1) { |
| 337 | const nextValidation = validations[current + 1] |
| 338 | if ( |
| 339 | (result || nextValidation.force || !nextValidation.skipEmpty) && |
| 340 | nextValidation.state === null |
| 341 | ) { |
| 342 | // If the next rule was never run then it has not been observed so it could never |
| 343 | // run again on its own. |
| 344 | nextValidation.queued = true |
| 345 | } |