Allow fields to dynamically update validation rules so that other fields can be referenced
This commit is contained in:
parent
cebfcb280b
commit
99cb7c8789
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
import Placeholder from "../Placeholder.svelte"
|
||||
import FieldGroupFallback from "./FieldGroupFallback.svelte"
|
||||
import { getContext } from "svelte"
|
||||
import { getContext, onMount } from "svelte"
|
||||
|
||||
export let label
|
||||
export let field
|
||||
|
@ -34,6 +34,9 @@
|
|||
fieldApi = formField?.fieldApi
|
||||
fieldSchema = formField?.fieldSchema
|
||||
|
||||
// Keep validation rules up to date
|
||||
$: fieldApi?.updateValidation(validation)
|
||||
|
||||
// Extract label position from field group context
|
||||
$: labelPositionClass =
|
||||
labelPosition === "above" ? "" : `spectrum-FieldLabel--${labelPosition}`
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
// Create validation function based on field schema
|
||||
const schemaConstraints = schema?.[field]?.constraints
|
||||
const validate = createValidatorFromConstraints(
|
||||
const validator = createValidatorFromConstraints(
|
||||
schemaConstraints,
|
||||
validationRules,
|
||||
field,
|
||||
|
@ -47,10 +47,11 @@
|
|||
fieldMap[field] = {
|
||||
fieldState: makeFieldState(
|
||||
field,
|
||||
validator,
|
||||
defaultValue,
|
||||
disabled || fieldDisabled || isAutoColumn
|
||||
),
|
||||
fieldApi: makeFieldApi(field, defaultValue, validate),
|
||||
fieldApi: makeFieldApi(field, defaultValue),
|
||||
fieldSchema: schema?.[field] ?? {},
|
||||
}
|
||||
|
||||
|
@ -93,9 +94,11 @@
|
|||
]
|
||||
|
||||
// Creates an API for a specific field
|
||||
const makeFieldApi = (field, defaultValue, validate) => {
|
||||
const makeFieldApi = field => {
|
||||
// Sets the value for a certain field and invokes validation
|
||||
const setValue = (value, skipCheck = false) => {
|
||||
const { fieldState } = fieldMap[field]
|
||||
const { defaultValue, validator } = get(fieldState)
|
||||
|
||||
// Skip if the value is the same
|
||||
if (!skipCheck && get(fieldState).value === value) {
|
||||
|
@ -103,7 +106,7 @@
|
|||
}
|
||||
|
||||
const newValue = value == null ? defaultValue : value
|
||||
const newError = validate ? validate(newValue) : null
|
||||
const newError = validator ? validator(newValue) : null
|
||||
|
||||
// Update field state
|
||||
fieldState.update(state => {
|
||||
|
@ -127,15 +130,20 @@
|
|||
return !newError
|
||||
}
|
||||
|
||||
// Clears the value of a certain field back to the initial value
|
||||
const clearValue = () => {
|
||||
const { fieldState } = fieldMap[field]
|
||||
const { defaultValue } = get(fieldState)
|
||||
const newValue = initialValues[field] ?? defaultValue
|
||||
|
||||
// Update field state
|
||||
fieldState.update(state => {
|
||||
state.value = newValue
|
||||
state.error = null
|
||||
return state
|
||||
})
|
||||
|
||||
// Update form state
|
||||
formState.update(state => {
|
||||
state.values = { ...state.values, [field]: newValue }
|
||||
delete state.errors[field]
|
||||
|
@ -144,9 +152,37 @@
|
|||
})
|
||||
}
|
||||
|
||||
// Updates the validator rules for a certain field
|
||||
const updateValidation = validationRules => {
|
||||
const { fieldState } = fieldMap[field]
|
||||
const { value, error } = get(fieldState)
|
||||
|
||||
// Create new validator
|
||||
const schemaConstraints = schema?.[field]?.constraints
|
||||
const validator = createValidatorFromConstraints(
|
||||
schemaConstraints,
|
||||
validationRules,
|
||||
field,
|
||||
table
|
||||
)
|
||||
|
||||
// Update validator
|
||||
fieldState.update(state => {
|
||||
state.validator = validator
|
||||
return state
|
||||
})
|
||||
|
||||
// If there is currently an error, run the validator again in case
|
||||
// the error should be cleared by the new validation rules
|
||||
if (error) {
|
||||
setValue(value, true)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
setValue,
|
||||
clearValue,
|
||||
updateValidation,
|
||||
validate: () => {
|
||||
const { fieldState } = fieldMap[field]
|
||||
setValue(get(fieldState).value, true)
|
||||
|
@ -155,13 +191,15 @@
|
|||
}
|
||||
|
||||
// Creates observable state data about a specific field
|
||||
const makeFieldState = (field, defaultValue, fieldDisabled) => {
|
||||
const makeFieldState = (field, validator, defaultValue, fieldDisabled) => {
|
||||
return writable({
|
||||
field,
|
||||
fieldId: `id-${generateID()}`,
|
||||
value: initialValues[field] ?? defaultValue,
|
||||
error: null,
|
||||
disabled: fieldDisabled,
|
||||
defaultValue,
|
||||
validator,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue