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

formdata-helper

v0.3.0

Published

Parse FormData into a structured JavaScript object with coerced primitives including TypeScript support

Downloads

480

Readme

formdata-helper

Parse FormData into a structured JavaScript object with coerced primitives

// Optional: Add TypeScript typing to the response values.
type SignUp = {
  email: string;
  password: string;
  age: number;
  terms: boolean;
  // With multi-select type fields, choosing one item will result in a string value.
  favorites: string | string[];
  resume: File;
};

// Create some FormData. You likely will just pass form data
// and not manually create it like this.
const formData = new FormData();
formData.set("email", "[email protected]");
formData.set("password", "s3kret!");
formData.set("age", "29");
formData.set("terms", "true");
formData.append("favorites", "TypeScript");
formData.append("favorites", "Svelte");
formData.set(
  "resume",
  new File(["Did lots of stuff"], "resume.txt", { type: "text/plain" })
);
const data = parseForm<SignUp>(formData);

// Returns the following structured data:
data.email; // "[email protected]"
data.password; // "s3kret!"
data.age; // 29
data.terms; // true
data.favorites; // ["TypeScript", "Svelte"]
data.resume; // File { name: "resume.txt", type: "text/plain" }

Purpose

Sometimes, working with FormData can be a pain in the bum, especially when working with large forms or when lots of form data needs to be coerced.

This simple tool takes an instance of FormData and returns a structured JavaScript object with coerced values of primitive types (boolean, number) and creates Arrays for grouped fields like multi-selects and multiple checkboxes. FormData is used in a lot of places where you may need to interact with its values:

  • new FormData(document.querySelector("form"))
  • WebWorker
  • SvelteKit +server or +page.server responses
  • Etc...

This library should work in all these cases, if it doesn't, please open an issue!

You can use the data parsed by formdata-helper to pass to your validation logic, say using Zod.

Features

  • Coerces various common value types into an Object:
    • "on" (for checkboxes), and "true" and "false" are coerced to booleans which is the value a type="checkbox" or type="radio" field will return.
    • Numbers strings are converted to numbers (e.g. "1.5" becomes 1.5)
      • Strings with numbers will not (e.g. "hello1", "1hello" or "he11o" will be strings)
    • Grouped fields like multi <select>s or <input type="checkbox"> are turned into Arrays (like "favorites": [ "TypeScript", "svelte" ]).
  • Works in the browser, Node or most other environments (exports CommonJS and ESM modules)
  • Has decent TypeScript support
    • Can declare a return type which the form defaults value is checked against (see below).
  • No dependencies! ✨
  • Tiny: about ~617B gzipped

Out of scope features

And some things that are beyond the scope of this library:

  • Doesn't validate the incoming data. For that, checkout Zod, Yup, io-ts, Runtypes or joi
  • Doesn't look at what field types you have and intelligently parse them. Since FormData doesn't give us this type of information, there is nothing we can know about the data in it, so we just do a naive parsing of the data. If you need something more robust, look elsewhere!
  • Since we don't know the types of the data, if a field is empty, it will always be resolved to an empty string. Keep this in mind when working with the data.

Install

npm i formdata-helper

Usage

Assuming the following form data:

<form>
  <input type="text" name="name" value="Jane Doe" />
  <input type="checkbox" name="favoriteFruits" value="Banana" checked />
  <input type="checkbox" name="favoriteFruits" value="Mango" checked />
</form>

parseFormData will return a structured JavaScript object:

import { parseFormData } from "formdata-helper";

const formData = new FormData(document.querySelector("form"));
const data = parseFormData(formData);

data becomes:

{
  name: "Jane Doe",
  favoriteFruits: [ "Banana", "Mango" ],
}

Configuration

Passing custom configuration options (all are shown below):


const formData = new FormData()
formData.append("email": "[email protected]")
formData.append("likesTypeScript": "yes") // will coerce to `true` with the below `truthy` option.
// `name` will get automatically set with `defaults` option.

parseFormData(formData, {
  defaults: { name: "Guest" },
  falsy: ["false", "f"],
  truthy: ["yes", "y"],
});

TypeScript usage

/**
 * Define a return type for the data.
 * Note that return value is actually Partial<MyFormData> because
 * we cannot guarantee the presence of any values in the provided `FormData`
 * so all return values are possibly `undefined`.
 */
type MyFormData = {
  username: string;
  age: number;
  // Any multi-select or group of checkboxes can be either a
  // single string or an array of strings.
  interests: string | string[];
  admin: boolean;
};

// With all options:
parseFormData<MyFormData>(formData, {
  defaults: {
    username: "guest",
    interests: ["TypeScript"],
    admin: false,
  },
});

Please note that if you want to use an interface instead of a type, you have to extend from StructuredFormData type exported from this package:

import { StructuredFormData } from "formdata-helper";

interface MyFormData extends StructuredFormData {
  username: string;
  age: number;
  interests: string[];
  admin: boolean;
}

SvelteKit usage

You can use this helper in your +server and +page.server files to parse incoming form data from form submissions in your Svelte pages.

import subscribeUser from "./subscribe-user";
import { parseFormData } from "formdata-helper";
import type { RequestHandler } from "./$types";
import { json } from "@sveltejs/kit";

type RequestData = {
  email: string;
  subscribe: boolean;
};

export const POST: RequestHandler = async ({ request }) => {
  const formData = await request.formData();
  const data = parseFormData<RequestData>(formData);

  if (data.subscribe && data.email) {
    await subscribeUser(data.email);
  }

  return json(data);
};

API

Type signatures:

type StructuredFormValue =
  | string
  | boolean
  | number
  | File
  | StructuredFormValue[];

type StructuredFormData = Record<string, StructuredFormValue>;

interface Configuration<T> {
  defaults?: Partial<T>;
  falsy?: string | string[];
  truthy?: string | string[];
}

parseFormData<T>(data: FormData, configuration?: Configuration)

Development

License

MIT

Credits

Created by Dana Woodman