swyxio / swyxdotio

This is the repo for swyx's blog - Blog content is created in github issues, then posted on swyx.io as blog pages! Comment/watch to follow along my blog within GitHub
https://swyx.io
MIT License
339 stars 45 forks source link

How to use SvelteKit with Netlify Forms #288

Closed swyxio closed 2 years ago

swyxio commented 2 years ago

source: devto devToUrl: "https://dev.to/swyx/how-to-use-sveltekit-with-netlify-forms-5gmj" devToReactions: 35 devToReadingTime: 4 devToPublishedAt: "2021-04-25T22:28:24.272Z" devToViewsCount: 1362 title: How to use SvelteKit with Netlify Forms published: true description: a simple tutorial category: tutorial tags: Svelte, Netlify slug: sveltekit-netlify-forms cover_image: https://user-images.githubusercontent.com/6764957/116011560-3dda9480-a658-11eb-8954-fd8cf7160ae2.png canonical_url: https://www.swyx.io/sveltekit-netlify-forms

This is a direct answer to this SvelteKit issue. I see a lot of JS developers struggle with using Netlify Forms, so I want to help.

9 Min Video Walkthru

This is the video version of the instructions below.

{% youtube cj3f2Xth5Mk %}

Context

Netlify Forms were designed primarily for traditional static site generators like Hugo and Jekyll, using HTML crawling to initialize forms. The idea is like this:

Many JS framework users struggle to use them because:

Optional Features You May Want

What I cover here is just the simplest solution to help people solve the immediate pain point. You can also:

I'll come back and add that to this blogpost if I ever get the time. Pls yell at me to indicate interest or i wont do it.

SvelteKit Setup Instructions

Project Init

Go through the standard SvelteKit setup:

npm init svelte@next myapp       
cd myapp
npm i

You can set up GitHub/Netlify either thru CLI or UI - I found some bugs with Netlify CLI when I tried this but it might be fixed by the time you read this:

# optional: set up git/github/netlify deploy via CLI
git init && git add . && git commit -m "hi"
gh repo create # have the github cli installed
ntl init # netlify cli

or you can just use the UIs for each service

Add SvelteKit Netlify Adapter

npm i -D @sveltejs/adapter-netlify@next       

then add it to svelte.config.cjs:

const adapter = require('@sveltejs/adapter-netlify');
module.exports = {
    kit: {
        adapter: adapter(), // currently the adapter does not take any options
        target: '#svelte',
        prerender: {
            crawl: true,
            enabled: true,
            force: true,
            pages: ['*'],
        },
    }
};

then add a netlify.toml file at project root:

[build]
  command = "npm run build"
  publish = "build/"
  functions = "functions/"

You can see these instructions in my netlify adapter docs.

Add the Prerendered Form

Head to /src/routes/index.svelte and add the form accordingly.

<script context="module">
    export const prerender = true;
</script>

<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>

<form name="test" method="post" netlify netlify-honeypot="bot-field">
    <input type="hidden" name="form-name" value="test" />
    <input type="text" name="bot-field" />
    <p>
        <label>Your Name: <input type="text" name="name" /></label>
    </p>
    <p>
        <label>Your Email: <input type="email" name="email" /></label>
    </p>
    <p>
        <label>Message: <textarea name="message" /></label>
    </p>
    <p>
        <button type="submit">Send</button>
    </p>
</form>

Deploy

Now you should be able to push to GitHub and have it build and render the form successfully.

Examples:

Screenshots

image

image

image

image

Graveyard: AJAX Example

Warning: this is untested code - I ran out of time but dumping it here anyway in case it helps someone

If you want an AJAX experience for your form here is some untested code I was working on that may help you get going:

<script context="module">
  export const prerender = true;
</script>

<script>
  let isSubmitting = false;

  const handleSubmit = (e) => {
    let myForm = document.getElementById("test");
    let formData = new FormData(myForm);
    isSubmitting = true;
    return fetch("/", {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: new URLSearchParams(formData).toString(),
    })
      .then(() => {
        console.log("Form successfully submitted");
        isSubmitting = false;
        myForm.reset();
      })
      .catch((error) => {
        alert(error);
        isSubmitting = false;
      });
  };
</script>

<h1>Welcome to SvelteKit</h1>
<p>
  Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation
</p>

<form
  id="test"
  name="test"
  on:submit|preventDefault={handleSubmit}
  netlify
  netlify-honeypot="bot-field"
>
  <input type="hidden" name="form-name" value="test" />
  <input type="text" name="bot-field" style="opacity: 0" />
  <p>
    <label>Your Name: <input type="text" name="name" /></label>
  </p>
  <p>
    <label>Your Email: <input type="email" name="email" /></label>
  </p>
  <p>
    <label>Message: <textarea name="message" /></label>
  </p>
  <p>
    {#if isSubmitting}
      <div>Submitting</div>
    {:else}
      <button type="submit">Send</button>
    {/if}
  </p>
</form>
rchrdnsh commented 2 years ago

The AJAX example did indeed work for me, and now I have a nice UI/UX for my form...thank you XD

secondl1ght commented 2 years ago

The AJAX example did indeed work for me, and now I have a nice UI/UX for my form...thank you XD

@rchrdnsh Can I see your code? I tried the example and could not get it working for some reason.

navsubrm commented 7 months ago

I think I found a better way after seeing what you did here. I would love your feedback on the idea. Your post was really helpful to get started. I put stuff in different places and used the Netlify forms as almost an API route from the rest of my app. The explanation is at https://answers.netlify.com/t/sveltekit-form-action-plus-netlify-form-submission/88515/5?u=navsubrm

I did the form with the +page.server.js controlling the form validation and submission to allow for not having JavaScript enabled. It just required a couple of changes with where to set the fetch to and placing all of the pre-rendered forms in a single location and just posting the data to them from whatever route I invoke the post from. Thank you for the help!