Skip to content

Commit 62c82b7

Browse files
committed
customValidity now handles objects.
1 parent 5add30f commit 62c82b7

File tree

7 files changed

+108
-19
lines changed

7 files changed

+108
-19
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
### Fixed
1515

1616
- Inlined the [SuperDebug](https://superforms.rocks/super-debug) css, to prevent it from being automatically bundled due to it being a default import.
17+
- The [customValidity](https://superforms.rocks/concepts/error-handling#customvalidity) option now handles object errors, and can refer to any part of the schema.
1718

1819
## [2.14.0] - 2024-05-26
1920

src/lib/client/customValidity.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,14 @@ export function setCustomValidityForm(
2525
continue;
2626
}
2727

28-
const error = traversePath(errors, splitPath(el.name));
29-
setCustomValidity(el, error?.value);
30-
if (error?.value) return;
28+
const path = traversePath(errors, splitPath(el.name));
29+
const error =
30+
path && typeof path.value === 'object' && '_errors' in path.value
31+
? path.value._errors
32+
: path?.value;
33+
34+
setCustomValidity(el, error);
35+
if (error) return;
3136
}
3237
}
3338

src/lib/client/superForm.ts

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,7 @@ export function superForm<
778778
if (skipValidation || !event || !options.validators || options.validators == 'clear') {
779779
if (event?.paths) {
780780
const formElement = event?.formElement ?? EnhancedForm_get();
781-
if (formElement) Form__clearCustomValidity(formElement, event.paths);
781+
if (formElement) Form__clearCustomValidity(formElement);
782782
}
783783
return;
784784
}
@@ -797,20 +797,14 @@ export function superForm<
797797
return result;
798798
}
799799

800-
function Form__clearCustomValidity(
801-
formElement: HTMLFormElement,
802-
paths: (string | number | symbol)[][]
803-
) {
800+
function Form__clearCustomValidity(formElement: HTMLFormElement) {
804801
const validity = new Map<string, { el: HTMLElement; message: string }>();
805802
if (options.customValidity && formElement) {
806-
for (const path of paths) {
807-
const name = CSS.escape(mergePath(path));
808-
const el = formElement.querySelector<HTMLElement>(`[name="${name}"]`);
809-
if (el) {
810-
const message = 'validationMessage' in el ? String(el.validationMessage) : '';
811-
validity.set(path.join('.'), { el, message });
812-
updateCustomValidity(el, undefined);
813-
}
803+
for (const el of formElement.querySelectorAll<HTMLElement & { name: string }>(`[name]`)) {
804+
if (typeof el.name !== 'string' || !el.name.length) continue;
805+
const message = 'validationMessage' in el ? String(el.validationMessage) : '';
806+
validity.set(el.name, { el, message });
807+
updateCustomValidity(el, undefined);
814808
}
815809
}
816810
return validity;
@@ -828,7 +822,7 @@ export function superForm<
828822
let validity = new Map<string, { el: HTMLElement; message: string }>();
829823

830824
const formElement = event.formElement ?? EnhancedForm_get();
831-
if (formElement) validity = Form__clearCustomValidity(formElement, event.paths);
825+
if (formElement) validity = Form__clearCustomValidity(formElement);
832826

833827
traversePaths(errors, (error) => {
834828
if (!Array.isArray(error.value)) return;
@@ -848,7 +842,7 @@ export function superForm<
848842
const { el, message } = validity.get(joinedPath)!;
849843

850844
if (message != error.value) {
851-
updateCustomValidity(el, error.value);
845+
setTimeout(() => updateCustomValidity(el, error.value));
852846
// Only need one error to display
853847
validity.clear();
854848
}

src/routes/(v2)/v2/Navigation.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@
6161
'reset-errors',
6262
'schemasafe-types',
6363
'discriminated-union',
64-
'simple-tainted'
64+
'simple-tainted',
65+
'validity-objects'
6566
].sort();
6667
</script>
6768

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { zod } from '$lib/adapters/zod.js';
2+
import { message, superValidate } from '$lib/server/index.js';
3+
import { schema } from './schema.js';
4+
import { fail } from '@sveltejs/kit';
5+
6+
export const load = async () => {
7+
const form = await superValidate(
8+
{
9+
priceRules: [
10+
{
11+
priceCategory: { value: '' }
12+
}
13+
]
14+
},
15+
zod(schema),
16+
{ errors: false }
17+
);
18+
return { form };
19+
};
20+
21+
export const actions = {
22+
default: async ({ request }) => {
23+
const formData = await request.formData();
24+
console.log(formData);
25+
26+
const form = await superValidate(formData, zod(schema));
27+
console.log(form);
28+
29+
if (!form.valid) return fail(400, { form });
30+
31+
return message(form, 'Posted OK!');
32+
}
33+
};
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<script lang="ts">
2+
import { zod } from '$lib/adapters/zod.js';
3+
import { superForm } from '$lib/client/index.js';
4+
import SuperDebug from '$lib/client/SuperDebug.svelte';
5+
import { schema } from './schema.js';
6+
7+
export let data;
8+
9+
const { form, errors, tainted, message, enhance } = superForm(data.form, {
10+
taintedMessage: false,
11+
dataType: 'json',
12+
customValidity: true,
13+
validators: zod(schema)
14+
});
15+
</script>
16+
17+
<SuperDebug data={{ $form }} />
18+
19+
{#if $message}<h4>{$message}</h4>{/if}
20+
21+
<form method="POST" use:enhance>
22+
<label>
23+
Name: <input
24+
bind:value={$form.priceRules[0].priceCategory.value}
25+
type="text"
26+
name="priceRules"
27+
/>
28+
</label>
29+
<div>
30+
<button>Submit</button>
31+
</div>
32+
</form>
33+
34+
<style lang="scss">
35+
form {
36+
margin: 2rem 0;
37+
38+
input {
39+
background-color: #dedede;
40+
}
41+
}
42+
</style>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { z } from 'zod';
2+
3+
export const schema = z.object({
4+
priceRules: z
5+
.array(
6+
z.object({
7+
priceCategory: z.object({
8+
value: z.string().min(2)
9+
})
10+
})
11+
)
12+
.min(2)
13+
});

0 commit comments

Comments
 (0)