Skip to content

Instantly share code, notes, and snippets.

@domi-nik-
Last active January 3, 2023 11:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save domi-nik-/a9830d2cd9cfe740ffd24b74e02f70af to your computer and use it in GitHub Desktop.
Save domi-nik-/a9830d2cd9cfe740ffd24b74e02f70af to your computer and use it in GitHub Desktop.
HowTo "Netlify Forms" with vuejs3, Vite, FormKit

How to use "Netlify Forms" with vuejs3

This little README shall enable vuejs3 beginners to use "Netlify Forms" for easy forms manageent, cost efficency and simplicity.

Install nodejs via nvm

nodejs version 18 ( zur Zeit des Schreibens: 18.12.1 Node) (wegen unterstuetzung, 19 wohl zu aktuell ist noch)

https://github.com/nvm-sh/nvm

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash

bsaic usage from the docs:

$ nvm use 16
Now using node v16.9.1 (npm v7.21.1)
$ node -v
v16.9.1
$ nvm use 14
Now using node v14.18.0 (npm v6.14.15)
$ node -v
v14.18.0
$ nvm install 12
Now using node v12.22.6 (npm v6.14.5)
$ node -v
v12.22.6

Was habe ich gemacht:

vm install 18
nvm use 18

Install netlify-cli

General docs: https://docs.netlify.com/cli/get-started/

npm install netlify-cli -g

Link project

cd $PROJECTDIRECTORY
netlify link

Install vuejs3 Project (Vite, Router, etc.)

https://github.com/vuejs/create-vue

I choose the following: Vue Router, ESLint, Prettier and Vite is default with the create-vue installer.

npm create vue@3                                                                                                    INT ✘  

Vue.js - The Progressive JavaScript Framework

✔ Project name: … vuejs3-forms
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit Testing? … No / Yes
✔ Add an End-to-End Testing Solution? › No
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes

Scaffolding project in /home/dbittl/vuejs3-forms...

Done. Now run:

  cd vuejs3-forms
  npm install
  npm run lint
  npm run dev

As I prefere yarn over npm I do the following:

cd vuejs3-forms
yarn install
yarn run dev

All node-modules are now installed and the dev-server is started, just to see if everything compiles and works.

Install FormKit

General dosc: https://formkit.com/getting-started/installation

yarn add @formkit/vue
yarn add promise await async

And then edit the main.js:

// main.js
import { createApp } from 'vue'
import router from './router'
import { plugin, defaultConfig } from '@formkit/vue'

import App from './App.vue'

createApp(App).use(plugin, defaultConfig, router).mount('#app')

Little test if everything still works:

yarn run dev

Simple Form for testing

First I delete the boilerplate from the installer and create new compononents (form,succes,fail), adjust the routing and then go on.

// @router/index.js
import { createRouter, createWebHistory } from "vue-router"

// import Views for router
import Form from '@/views/FormView.vue'
import SubmissionSuccess from '@/views/SubmissionSuccessView.vue'
import SubmissionFailure from "@/views/SubmissionFailureView.vue"

const routes= [
    {path: '/', name: 'Form', component: Form },
    {path: '/success', name: 'Success', component: SubmissionSuccess },
    {path: '/failure', name: 'Failure', component: SubmissionFailure }
]


const router = createRouter( {
    history: createWebHistory(),
    routes
})

export default router
// main.js
import { createApp } from 'vue'
import router from '@/router'
import { plugin, defaultConfig } from '@formkit/vue'


import App from './App.vue'

createApp(App)
.use(plugin, defaultConfig) // formkit
.use(router) // router
.mount('#app')
// @views/FormView.vue
<template>
    <div class='form'>
        <h1>Form</h1>
        <Form />
    </div>
</template>

<script>
import Form from "@/components/Form.vue"

export default {
    name: "FormView",
    components: {
        Form,
    },
};

</script>

Setup Prerendering or plain html

So that Netlify recognises the form, we need to create a prerendering (flat html files) of the project or we just create an minimal html-form in /public/index.html so we don't need a extra plugin or compiler settings.

// /index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Website</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
    <form name="main-form" netlify netlify-honeypot="bot-field" hidden>
      <input type="text" name="firstname" />
      <input type="text" name="lastname" />
    </form>
  </body>
</html>

How to send to netlify

// components/Form.vue
<script setup>
import { ref } from 'vue';
import { useRouter } from 'vue-router';

const router = useRouter()

const formData = ref({
    firstname: "First Name",
    lastname: "Last Name" 
});

function encode(data) {
  return Object.keys(data)
    .map(
      (key) =>
        encodeURIComponent(key) + "=" + encodeURIComponent(data[key])
    )
    .join("&");
}

async function handleSubmit(data) {
    //await wait(3000);
    console.log(data);
    fetch("/", {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: encode ({
        "form-name": "main-form",
        "firstname": data.firstname,
        "lastname": data.lastname
    }),
    })
    .then(() => router.replace({ path: '/success' })) // forward to another page
    .catch((error) => alert(error));
} 

</script>

<template>
<FormKit type="form" 
    name="main-form"   
    :value="formData" 
    @submit="handleSubmit"
    submit-label="Senden">
    <FormKit
      type="text"
      name="firstname"
      label="First Name"
    />
    <FormKit
    type="text"
    name="lastname"
    label="Last Name"
    />
</FormKit>    
</template>

<style>

</style>

All the parts have to macth with the index.html-form. Like form-name and input files like lastname nad firstname in this example.

Install tailwind

General docs: https://tailwindcss.com/docs/guides/vite#vue

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Edit the tailwind.config.js to add template files:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./index.html",
    "./src/**/*.{vue,js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Add a file 'style.css' with the following content:

// src/style.css
@tailwind base;
@tailwind components;
@tailwind utilities;

Now import the file in your main.js

// main.js

[...]

import './style.css'

[...]

Install formit-themes

General docs: https://formkit.com/guides/create-a-tailwind-theme

npm install @formkit/themes

Adjust the main.js

import { createApp } from 'vue'
import router from '@/router'
import { plugin, defaultConfig } from '@formkit/vue'
import { generateClasses } from '@formkit/themes'


import './style.css'
import theme from './theme.js'


import App from './App.vue'

createApp(App)
.use(
    plugin,
    defaultConfig({
      config: {
        classes: generateClasses(theme),
      },
    })
  ) // FormKit
.use(router) // router
.mount('#app')

Create the themes.js as shown in the formkit docs.

Save your forms data in a database (firebase) with Netlify Functions (serverless)

https://www.netlify.com/blog/2018/09/14/forms-and-functions/

Links

This README is based on a lot of other sources:

https://vueschool.io/courses/robust-vue-js-forms-with-formkit

https://www.koderhq.com/tutorial/vue/http-fetch/

https://docs.netlify.com/forms/setup/ (Netlify Forms Setup)

https://www.netlify.com/blog/2018/09/07/how-to-integrate-netlify-forms-in-a-vue-app/ (not so up to date sadly)

https://docs.netlify.com/functions/overview/ (Netlify Functions)

Full source code

You can find the source code here:

https://github.com/domi-nik-/netlify-forms-vuejs3-vite

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment