'Svelte - Form submission and action

I am trying to submit a form using svelte and yup. Whenever the form is submitted, the information must be send into the action part of the form (a CGI on a cgi-bin folder). It has been replaced now by stackoverflow url for debugging purpose.

<script>
    import { createForm } from 'svelte-forms-lib';
    import * as yup from "yup";
    const phoneRegExp = /^(?:(?:\+|00)32[\s.-]{0,3}(?:\(0\)[\s.-]{0,3})?|0)((?:(?:[\s.-]?\d{2}){1})|(?:(?:[\s.-]?\d{3}){1}))((?:[\s.-]?\d{2}){3}|(?:[\s.-]?\d{3}){2})$/

    const { form, errors, state,touched,isValid,isSubmitting,isValidating, handleChange, handleSubmit } = createForm({
      initialValues: {
        name: '',
         email: '',
         phone: '',
         availability: ' ',
        vieprivee: false, 
      },
      validationSchema: yup.object().shape({
        name: yup
          .string()
          .required("Name is required")
          .min(3, "Name is too short"),
        email: yup
          .string()
          .email("Format is invalid")
          .when('phone',{
            is:(phone) => !phone || phone.length ===0,
            then: yup.string().email().required().default(''),
            otherwise:yup.string().default('')
          }),
        phone: yup
          .string()
          .when('email',{
            is:(email) => !email || email.length === 0,
            then: yup
            .string()
            .matches(phoneRegExp, "Format is invalid")
            .required()
            .default(''),
            otherwise: yup.string().default('')
          }),
        vieprivee: yup
          .bool()
          .required("Consent is required")
          .oneOf([true],"Consent is required"),
        availability: yup
          .mixed()
          .notRequired()
          .default(" "),
      },[['email','phone']]),
      validate: (values) => {
      alert(JSON.stringify(values));
      }

      onSubmit: values => {

        alert(JSON.stringify(values));
      }
    });
  </script>

  <style>
    .hide { position:absolute; top:-1px; left:-1px; width:1px; height:1px; }
  </style>
  <iframe name="hiddenFrame" class="hide"></iframe>


<form  action="http://stackoverflow.com"  target="hiddenFrame" id="formContact" on:submit={handleSubmit} class:valid={$isValid}>
  <!-- action="./cgi-bin/feedback_form.cgi" method="post"  -->
  <div id="veterinexpowin" />
  <label for="name">Name</label>
  <input
    id="name"
    name="name"
    on:keyup={handleChange}
    on:blur={handleChange}
    bind:value={$form.name} />
  {#if $errors.name && $touched.name}<small>{$errors.name}</small>{/if}

  <label for="phone">Phone</label>
  <input
    id="phone"
    name="phone"
    on:keyup={handleChange}
    on:blur={handleChange}
    bind:value={$form.phone} />
  {#if $errors.phone && $touched.phone}<small>{$errors.phone}</small>{/if}

  <label for="email">Email</label>
  <input
    id="email"
    name="email"
    on:keyup={handleChange}
    on:blur={handleChange}
    bind:value={$form.email} />
    {#if $errors.email && $touched.email}<small>{$errors.email}</small>{/if}

  
  <label for="availability">Comments / Availability</label>
  <textarea
    id="availability"
    name="availability"
    on:keyup={handleChange}
    on:blur={handleChange}
    bind:value={$form.availability} />
    {#if $errors.availability && $touched.availability}<small>{$errors.availability}</small>{/if}
    <br>
    
    <input 
      type="checkbox" 
      id="vieprivee" 
      name="vieprivee" 
      class="checkboxvieprivee"
      on:change={handleChange}
      on:blur={handleChange}
      bind:value={$form.vieprivee}/>
      <label for="vieprivee"><span class="spanvieprivee">I read and understand the  <a href="PolitiqueViePriveeByVets.pdf" target="_blank"> GDPR</a>  <br/>
        and I accept it.</span></label>
      {#if $errors.vieprivee}<small>{$errors.vieprivee}</small>{/if}
      
      <button 
        id="contactButton" 
        type="submit" 
        class="contactButton" 
        disabled={!$isValid}
        value="Submit">
        Send
      </button>
    
</form>
  • The first field is for the name and is required.
  • The second field is for the phone and is only required if the third field(mail) is not filled in.
  • The third field is for the mail. It is only required if the second field(phone) is not filled in.
  • The fourth field is for the comments or the availability. It is not mandatory.
  • The last field is a checkbox. It must be checked to submit the form.

My error is that the action is not triggered. I'm not sure how to debug that.

Thanks for yout help



Solution 1:[1]

So after playing around with the 'on:submit' tag I found that leaving the handleSubmit only in the button was working. and calling as expected my CGI.

Solution 2:[2]

You can use:

  event.stopPropagation();
  event.preventDefault();

Example Svelte Component:

<script>
  function validate(event) {
    let valid = true;

    // perform validation here...
    // set validate to false as necessary

    if (!valid) {
      event.stopPropagation();
      event.preventDefault();
    }
  }
</script>

<main>
  <form method="post" action="/path/to/post" on:submit={(e) => validate(e)}>
    <label for="email">Email:</label><br />
    <input type="text" id="email" name="email" value="" /><br />

    <input type="submit" value="Submit" />
  </form>
</main>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Charley
Solution 2 Evan Closson