npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

svelte-form-validation

v1.0.5

Published

[![NPM Version](https://img.shields.io/npm/v/svelte-form-validation.svg?orange=blue)](https://npmjs.org/package/svelte-form-validation)

Downloads

10

Readme

Welcome to svelte-form-validation 👋

NPM Version

Svelte Form Validation Library

🏠 Homepage

Install

npm install svelte-form-validation

This package uses a popular Schema Validation library Yup. For documentation on how to create Validation Schema, checkout Yup's official Github Repo https://github.com/jquense/yup.

Basic Usage Example

src/routes/basic.svelte :

<script>
	import { createForm } from 'svelte-form-validation';
	import * as yup from 'yup';

	// Create Form Instance
	const { values, highlight, isValid } = createForm({
		// Initial Form Data
		values: {
			email: '',
			password: ''
		},
		// Form Validation using Yup
		validationSchema: yup.object().shape({
			email: yup.string().email().required(),
			password: yup.string().min(6).required()
		})
	});

	const onSubmit = () => {
		// "$values" contains current Form Data
		console.log($values);
	};
</script>

<form on:submit|preventDefault="{onSubmit}">
	<input type="text" name="email" bind:value="{$values.email}" use:highlight />
	<input type="password" name="password" bind:value="{$values.password}" use:highlight />

	<button type="submit" disabled="{!$isValid}">Submit</button>
</form>

Full Usage Example

demo/Full.svelte :

<script lang="ts">
  import { createForm } from "svelte-form-validation";
  import * as yup from 'yup';
  import UserAddressForm from "./UserAddressForm.svelte"; // Components

  // (Optional) Form's Data type will be automatically inferred from "values" in "createForm" if type of Data is not specified
  type FormData = {
    title: string,
    description: string,
    coverImage: FileList,
    users: {
      name: string,
      email: string,
      address: {
        state: string,
        city: string,
      },
    }[],
  };

  // Create Form Instance
  const {
    values, // Svelte Store<FormData> containing Form Data
    state, // Svelte Store<FormState> containing Form State - { [every_property]: { _touched: boolean, _errors: string[] }}
    isValid, // Svelte Store<boolean> containing entire Form's validation status
    isTouched, // Svelte Store<boolean> containing entire Form's touched status
    validateForm, // Function(highlight: 'none' | 'errors' | 'all' = 'none') for manually validting entire form
    handleChange, // Function(event: Event) to manually updating individual form control's state - can be used in place of "highlight" Action
    setTouched, // Function() for manually setting Form state as "touched"
    updateForm, // Function() for updating Form's Structure after Form Controls are Added or Removed in cases like Form Arrays
    highlight, // Svelte Action to be used with <input>, <select>, <textarea> or similar HTML input elements
    resetForm, // Reset the Form with optional new value and clear validation
  } = createForm<FormData>({
    // Initial Values of Form
    values: {
      title: "", // Simple String
      description: "", // Simple String
      coverImage: "", // File Input
      users: [], // Complex Form Array
    },
    // Validation Schema (Yup - https://github.com/jquense/yup)
    validationSchema: yup.object().shape({
      title: yup.string().min(8).required(),
      description: yup.string(),
      coverImage: yup.mixed().test(value => value?.length > 0), // Custom validation because yup does not suport file objects
      users: yup.array().of(
        yup.object().shape({
          name: yup.string().required(),
          email: yup.string().email().required(),
          address: yup.object().shape({
            state: yup.string().required(),
            city: yup.string(),
          }),
        }),
      )
    }),
    // CSS class validations, these options are also available in "highlight" action
    css: {
      enabled: true, // use CSS classes or not
      validClass: "is-valid", // CSS class added to valid form controls
      invalidClass: "is-invalid", // CSS class added to invalid form controls
      useValid: true, // Add CSS classes to valid form controls
      useInvalid: true, // Add CSS classes to invalid form controls
    },
    validateOnChange: true, // Whether to validate on "change" event of element and form value change
    validateOnBlur: true, // Whether to validate on "blur" event of element
  });

  // Add new user to Users Form Array
  const addUser = () => {
    // Update Form Data
    $values.users = [
      ...$values.users,
      {
        name: "",
        email: "",
        address: {
          state: "",
          city: "",
        },
      },
    ];
    updateForm(); // Manually trigger Form Update - Required
  };

  // Remove user from Users Form Array
  const removeUser = (index) => () => {
    $values.users = $values.users.filter((_, i) => i !== index); // Update Form Data
    $state.users = $state.users.filter((_, i) => i !== index); // Updating State is required after removing Form Controls
    updateForm(); // Manually trigger Form Update - Required
  };

  // Submit Form
  const onSubmit = () => {
    console.log($values); // Get Form Data
    // Reset form after submit
    resetForm({
      title: "",
      description: "",
      coverImage: "",
      users: [],
    });
  };

  $: console.log($values, $state); // Log Form Data and Form State on every Change
</script>

<form on:submit|preventDefault={onSubmit}>

    <input
        placeholder="Title"
        name="title"
        bind:value={$values.title}
        use:highlight={{ useValid: false }}
    />
    {#if $state.title._errors?.length}
        {#each $state.title._errors as error}
            <span class="error">{error}</span>
        {/each}
    {/if}

    <input
        placeholder="Description"
        name="description"
        bind:value={$values.description}
    />
    {#if $state.description._errors?.length}
        {#each $state.description._errors as error}
            <span class="error">{error}</span>
        {/each}
    {/if}

    <input
        name="coverImage"
        accept="image/*"
        bind:files={$values.coverImage}
        use:highlight
        type="file"
    />
    {#if $state.coverImage._errors?.length}
        {#each $state.coverImage._errors as error}
        <span class="error">{error}</span>
        {/each}
    {/if}

    {#if $values.coverImage?.length}
        <div class="image-preview">
            <img
            src={URL.createObjectURL($values.coverImage[0])}
            alt="Cover"
            height="150" />
        </div>
    {/if}

    {#each $values.users as user, index}
        <h2>
            User {user.name}
            <button type="button" on:click={removeUser(index)}>
                Remove User
            </button>
        </h2>

        <input
            placeholder="name"
            name="users[{index}].name"
            bind:value={user.name}
            use:highlight
        />
        {#if $state.users[index].name._errors?.length}
            {#each $state.users[index].name._errors as error}
                <span class="error">{error}</span>
            {/each}
        {/if}

        <input
            placeholder="email"
            name="users[{index}].email"
            bind:value={user.email}
            use:highlight
        />
        {#if $state.users[index].email._errors?.length}
            {#each $state.users[index].email._errors as error}
                <span class="error">{error}</span>
            {/each}
        {/if}

        <!-- Using with Components -->
        <UserAddressForm {values} {state} {highlight} {index} />

    {/each}

    <button type="button" on:click={addUser}>
        Add User
    </button>

    <button type="button" on:click={() => validateForm('errors')}>
        Validate Form
    </button>

    <button type="submit" disabled={!$isValid}>
        Submit
    </button>

</form>

<style>
    .valid {
        border: 1px solid green;
    }

    .invalid {
        border: 1px solid red;
    }

    .error {
        color: red;
    }
</style>

demo/UserAddressForm.svelte :

<script lang="ts">
	export let values: any;
	export let state: any;
	export let highlight;
	export let index: number;
</script>

<div>
	<input
		type="text"
		placeholder="State"
		bind:value="{$values.users[index].address.state}"
		name="users[{index}].address.state"
		use:highlight
	/>
	{#if $state.users[index].address.state._errors?.length}
	<div>
		{#each $state.users[index].address.state._errors as error}
		<span class="error">{error}</span>
		{/each}
	</div>
	{/if}

	<input
		type="text"
		placeholder="City"
		bind:value="{$values.users[index].address.city}"
		name="users[{index}].address.city"
		use:highlight
	/>
	{#if $state.users[index].address.city._errors?.length}
	<div>
		{#each $state.users[index].address.city._errors as error}
		<span class="error">{error}</span>
		{/each}
	</div>
	{/if}
</div>

🤝 Contributing

Contributions, issues and feature requests are welcome!

Feel free to check issues page.

Show your support

Give a ⭐️ if this project helped you!

📝 License

This project is MIT licensed.