Skip to content

Instantly share code, notes, and snippets.

@bojanv55
Last active November 3, 2021 16:15
Show Gist options
  • Save bojanv55/68836d9b9ec936cee40658915eb8fe6f to your computer and use it in GitHub Desktop.
Save bojanv55/68836d9b9ec936cee40658915eb8fe6f to your computer and use it in GitHub Desktop.
Svelte client/server form validation
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Dumber Gist</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
</head>
<!--
Dumber Gist uses dumber bundler, the default bundle file
is /dist/entry-bundle.js.
The starting module is pointed to "index" (data-main attribute on script)
which is your src/index.ts.
-->
<body>
<div id="root"></div>
<script src="/dist/entry-bundle.js" data-main="index"></script>
</body>
</html>
{
"dependencies": {
"svelte": "latest",
"zod": "^3.11.6",
"felte": "^0.8.5",
"@felte/validator-zod": "^0.3.4",
"@felte/reporter-dom": "^0.3.10"
}
}
<script lang="ts">
import { createForm } from 'felte';
import reporter from '@felte/reporter-dom';
import { validator } from '@felte/validator-zod';
import {z} from "zod";
const modelSchema = z.object({
requiredFiveChars: z.string().min(5, {message: "has to be at least 5 characters"}),
array: z.array(z.object({
name: z.string().min(7, {message: "has to be at least 7 characters"})
})),
subObject: z.object({
subSubObject: z.object({
subSubSubProp: z.string().nonempty({message: "cannot be empty"})
})
})
});
const { form, errors, data } = createForm<z.infer<typeof modelSchema>, ValidatorConfig>({
// ...
extend: [validator, reporter({ single: true })], // OR `extend: [validator],`
validateSchema: modelSchema,
// ...
onError: error => error,
initialValues: {
array: [],
subObject: {
subSubObject: {}
}
},
onSubmit: (values) => {
throw {
requiredFiveChars: 'This password already exists',
};
},
});
/* type modelType = z.infer<typeof modelSchema>;
const model : modelType = {
array: [],
subObject: {
subSubObject: {}
}
};*/
const addNew = () => {
$data.array = [...$data.array, {name:""}]
}
</script>
<main>
<h1>Form</h1>
<form use:form>
<label class="validation-message">Some prop:
<input type="text" name="requiredFiveChars" required>
<div class="error" data-felte-reporter-dom-for="requiredFiveChars" />
</label>
<label class="validation-message">Sub sub sub prop:
<input type="text" name="subObject.subSubObject.subSubSubProp">
<div class="error" data-felte-reporter-dom-for="subObject.subSubObject.subSubSubProp" />
</label>
<div class="array">
<h3>Array handling</h3>
{#each $data.array as _,index}
<label class="validation-message">Name:
<input type="text" name="array[{index}].name" data-felte-unset-on-remove required>
<div class="error" data-felte-reporter-dom-for="array[{index}].name" />
</label>
{/each}
<button type="button" on:click|preventDefault={addNew}>Add New</button>
</div>
<button type="submit">Send</button>
</form>
</main>
<style>
label{
display: block;
}
.error{
color: red;
}
.array{
margin: 40px;
}
</style>
import App from './App.svelte';
const app = new App({
target: document.getElementById('root'),
props: {
name: 'Svelte'
}
});
export default app;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment