Add validation for array field
This commit is contained in:
parent
04ce0abd46
commit
84d85664ef
|
@ -9,6 +9,7 @@
|
||||||
Body,
|
Body,
|
||||||
Input,
|
Input,
|
||||||
DatePicker,
|
DatePicker,
|
||||||
|
Multiselect,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { currentAsset, selectedComponent } from "builderStore"
|
import { currentAsset, selectedComponent } from "builderStore"
|
||||||
import { findClosestMatchingComponent } from "builderStore/storeUtils"
|
import { findClosestMatchingComponent } from "builderStore/storeUtils"
|
||||||
|
@ -102,6 +103,11 @@
|
||||||
Constraints.MinLength,
|
Constraints.MinLength,
|
||||||
Constraints.MaxLength,
|
Constraints.MaxLength,
|
||||||
],
|
],
|
||||||
|
["array"]: [
|
||||||
|
Constraints.Required,
|
||||||
|
Constraints.MinLength,
|
||||||
|
Constraints.MaxLength,
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
$: dataSourceSchema = getDataSourceSchema($currentAsset, $selectedComponent)
|
$: dataSourceSchema = getDataSourceSchema($currentAsset, $selectedComponent)
|
||||||
|
@ -109,7 +115,6 @@
|
||||||
$: schemaRules = parseRulesFromSchema(field, dataSourceSchema || {})
|
$: schemaRules = parseRulesFromSchema(field, dataSourceSchema || {})
|
||||||
$: fieldType = type?.split("/")[1] || "string"
|
$: fieldType = type?.split("/")[1] || "string"
|
||||||
$: constraintOptions = getConstraintsForType(fieldType)
|
$: constraintOptions = getConstraintsForType(fieldType)
|
||||||
|
|
||||||
const getConstraintsForType = type => {
|
const getConstraintsForType = type => {
|
||||||
return ConstraintMap[type]
|
return ConstraintMap[type]
|
||||||
}
|
}
|
||||||
|
@ -283,7 +288,7 @@
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<!-- Otherwise we render a component based on the type -->
|
<!-- Otherwise we render a component based on the type -->
|
||||||
{#if ["string", "number", "options", "longform"].includes(rule.type)}
|
{#if ["string", "number", "options", "longform", "array"].includes(rule.type)}
|
||||||
<Input
|
<Input
|
||||||
disabled={rule.constraint === "required"}
|
disabled={rule.constraint === "required"}
|
||||||
bind:value={rule.value}
|
bind:value={rule.value}
|
||||||
|
|
|
@ -47,6 +47,7 @@ const componentMap = {
|
||||||
// Some validation types are the same as others, so not all types are
|
// Some validation types are the same as others, so not all types are
|
||||||
// explicitly listed here. e.g. options uses string validation
|
// explicitly listed here. e.g. options uses string validation
|
||||||
"validation/string": ValidationEditor,
|
"validation/string": ValidationEditor,
|
||||||
|
"validation/array": ValidationEditor,
|
||||||
"validation/number": ValidationEditor,
|
"validation/number": ValidationEditor,
|
||||||
"validation/boolean": ValidationEditor,
|
"validation/boolean": ValidationEditor,
|
||||||
"validation/datetime": ValidationEditor,
|
"validation/datetime": ValidationEditor,
|
||||||
|
|
|
@ -2101,7 +2101,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "validation/string",
|
"type": "validation/array",
|
||||||
"label": "Validation",
|
"label": "Validation",
|
||||||
"key": "validation"
|
"key": "validation"
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,10 +40,15 @@
|
||||||
bind:fieldApi
|
bind:fieldApi
|
||||||
bind:fieldSchema
|
bind:fieldSchema
|
||||||
>
|
>
|
||||||
<Multiselect
|
{#if fieldState}
|
||||||
getOptionLabel={flatOptions ? x => x : x => x.label}
|
<Multiselect
|
||||||
getOptionValue={flatOptions ? x => x : x => x.value}
|
getOptionLabel={flatOptions ? x => x : x => x.label}
|
||||||
{placeholder}
|
getOptionValue={flatOptions ? x => x : x => x.value}
|
||||||
{options}
|
id={$fieldState.fieldId}
|
||||||
/>
|
disabled={$fieldState.disabled}
|
||||||
|
on:change={e => fieldApi.setValue(e.detail)}
|
||||||
|
{placeholder}
|
||||||
|
{options}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
@ -25,7 +25,7 @@ export const createValidatorFromConstraints = (
|
||||||
schemaConstraints.presence?.allowEmpty === false
|
schemaConstraints.presence?.allowEmpty === false
|
||||||
) {
|
) {
|
||||||
rules.push({
|
rules.push({
|
||||||
type: "string",
|
type: schemaConstraints.type == "array" ? "array" : "string",
|
||||||
constraint: "required",
|
constraint: "required",
|
||||||
error: "Required",
|
error: "Required",
|
||||||
})
|
})
|
||||||
|
@ -63,7 +63,7 @@ export const createValidatorFromConstraints = (
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inclusion constraint
|
// Inclusion constraint
|
||||||
if (exists(schemaConstraints.inclusion)) {
|
if (!schemaConstraints.type == "array" ? exists(schemaConstraints.inclusion) : false) {
|
||||||
const options = schemaConstraints.inclusion || []
|
const options = schemaConstraints.inclusion || []
|
||||||
rules.push({
|
rules.push({
|
||||||
type: "string",
|
type: "string",
|
||||||
|
@ -73,6 +73,18 @@ export const createValidatorFromConstraints = (
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inclusion constraint
|
||||||
|
if (schemaConstraints.type == "array" ? exists(schemaConstraints.inclusion[0]) : false ) {
|
||||||
|
const options = schemaConstraints.inclusion[0] || []
|
||||||
|
rules.push({
|
||||||
|
type: "array",
|
||||||
|
constraint: "inclusion",
|
||||||
|
value: options,
|
||||||
|
error: "Invalid value",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Date constraint
|
// Date constraint
|
||||||
if (exists(schemaConstraints.datetime?.earliest)) {
|
if (exists(schemaConstraints.datetime?.earliest)) {
|
||||||
const limit = schemaConstraints.datetime.earliest
|
const limit = schemaConstraints.datetime.earliest
|
||||||
|
@ -142,7 +154,7 @@ const evaluateRule = (rule, value) => {
|
||||||
* in the same format.
|
* in the same format.
|
||||||
* @param value the value to parse
|
* @param value the value to parse
|
||||||
* @param type the type to parse
|
* @param type the type to parse
|
||||||
* @returns {boolean|string|*|number|null} the parsed value, or null if invalid
|
* @returns {boolean|string|*|number|null|array} the parsed value, or null if invalid
|
||||||
*/
|
*/
|
||||||
const parseType = (value, type) => {
|
const parseType = (value, type) => {
|
||||||
// Treat nulls or empty strings as null
|
// Treat nulls or empty strings as null
|
||||||
|
@ -202,6 +214,13 @@ const parseType = (value, type) => {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type === "array") {
|
||||||
|
if (!Array.isArray(value) || !value.length) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
// If some unknown type, treat as null to avoid breaking validators
|
// If some unknown type, treat as null to avoid breaking validators
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -239,7 +258,7 @@ const maxValueHandler = (value, rule) => {
|
||||||
|
|
||||||
// Evaluates an inclusion constraint
|
// Evaluates an inclusion constraint
|
||||||
const inclusionHandler = (value, rule) => {
|
const inclusionHandler = (value, rule) => {
|
||||||
return value == null || rule.value.includes(value)
|
return value == null || rule.type == "array" ? rule.value.map(val => val === value) : rule.value.includes(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluates an equal constraint
|
// Evaluates an equal constraint
|
||||||
|
|
Loading…
Reference in New Issue