GithubHelp home page GithubHelp logo

what1s1ove / form-payload Goto Github PK

View Code? Open in Web Editor NEW
9.0 1.0 0.0 822 KB

Gets proper form payload – via form.elements.

Home Page: https://npmjs.com/package/form-payload

License: MIT License

JavaScript 100.00%
form form-controls form-data form-handling form-values

form-payload's Introduction

form-payload

Continuous Integration Continuous Delivery

Gets proper form payload – via form.elements.

Install

npm install form-payload

Demo

The library works perfectly with any framework. Just use a valid HTMLFormElement and form elements. If you want to add validation or any other functionality, create wrappers on top of the exported functions from the form-payload library.

Usage

<form name="resume">
  <label>CV: <input type="file" name="resume"></label>
</form>

<form name="mailing">
  <label>Email: <input type="email" name="mail" value="[email protected]"></label>
</form>

<form name="general">
  <label>Name: <input type="text" name="name" value="John"></label>
  <label>DOB: <input type="date" name="dob" value="2021-03-27"></label>
  <button type="submit">Submit</button>
</form>

<script>
  import { getFormPayload, getFormControlPayload } from 'form-payload';

  const {
    resume: resumeFormNode,
    mailing: mailingFormNode,
    general: generalFormNode,
  } = document.forms;

  resumeFormNode.addEventListener('change', (evt) => {
    // ❌ bad (hard to read, magic numbers, bulky, outdated approach)
    const file = evt.target.files?.[0] || null;

    // 🟡 better (modern, clear, but repetitive approach – violates DRY)
    const [file = null] = env.target.files ?? [];

    // ✅ ideal
    const file = getFormControlPayload(evt.target);
    // => File or null
  });

  mailingFormNode.addEventListener('input', (evt) => {
    const formControlPayload = getFormControlPayload(evt.target);
    // => '[email protected]'
  });

  generalFormNode.addEventListener('submit', (evt) => {
    evt.preventDefault();

    const formPayload = getFormPayload(generalFormNode);
    // => { name: 'John', dob: 'Sat Mar 27 2021 02:00:00 GMT+0200' }
  });
</script>

Value Correspondence Table

HTMLElement Attributes Included Return Value
HTMLInputElement type="text" string
HTMLInputElement type="password" string
HTMLInputElement type="search" string
HTMLInputElement type="url" string
HTMLInputElement type="tel" string
HTMLInputElement type="color" string
HTMLInputElement type="radio" string
HTMLInputElement type="hidden" string
HTMLInputElement type="email" string
HTMLInputElement type="email" and multiple Array<string>
HTMLInputElement type="number" number
HTMLInputElement type="range" number
HTMLInputElement type="checkbox" boolean
HTMLInputElement type="checkbox" and with [] in name Array<string> (See advanced usage)
HTMLInputElement type="date" Date
HTMLInputElement type="time" Date
HTMLInputElement type="month" Date
HTMLInputElement type="week" Date
HTMLInputElement type="datetime-local" Date
HTMLInputElement type="file" File or null
HTMLInputElement type="file" and multiple Array<File>
HTMLInputElement type="button" or type="submit" or type="reset" or type="image"
HTMLTextAreaElement string
HTMLSelectElement string
HTMLSelectElement multiple Array<string>
HTMLOutputElement string
HTMLFieldsetElement Object<name: string, value: unknown> (See advanced usage)
HTMLFieldsetElement with [] in name Array<Object<name: string, value: unknown>> (See advanced usage)
HTMLButtonElement
HTMLObjectElement

Advanced Usage

HTMLInputElement with type="checkbox" as array

getFormPayload returns an array of values for checked elements when using <input> with type="checkbox" and the [] symbol at the end of the name attribute of the <input> element itself.

<form name="shop">
  <label>Shop name: <input name="name" type="text" value="Shop #1"></label>
  <label>Apple <input name="fruits[]" type="checkbox" value="apple" checked></label>
  <label>Orange <input name="fruits[]" type="checkbox" value="orange"></label>
  <label>Banana <input name="fruits[]" type="checkbox" value="banana" checked></label>
  <button type="submit">Submit</button>
</form>

<script>
  import { getFormPayload } from 'form-payload';

  const { shop: shopFormNode } = document.forms;

  shopFormNode.addEventListener('submit', (evt) => {
    evt.preventDefault();

    const formPayload = getFormPayload(shopFormNode);
    // =>
    // {
    //   name: 'Shop #1',
    //   fruits: ['apple', 'banana'],
    // }
  })
</script>

HTMLFieldsetElement as object

getFormPayload/getFormControlPayload returns a nested objects when using the <fieldset> element. The key name will be based on the name attribute of the <fieldset> element itself. Nesting of <fieldset> elements within each other can be infinite. getFormPayload/getFormControlPayload collects all values recursively.

<form name="company">
  <label>Company name: <input name="name" type="text" value="FreshHarvest Hub"></label>
  <fieldset name="shop">
    <label>Shop name: <input name="name" type="text" value="Shop #1"></label>
    <label>Open: <input name="isOpen" type="checkbox" checked></label>
  </fieldset>
  <button type="submit">Submit</button>
</form>

<script>
  import { getFormPayload } from 'form-payload';

  const { company: companyFormNode } = document.forms;

  companyFormNode.addEventListener('submit', (evt) => {
    evt.preventDefault();

    const formPayload = getFormPayload(companyFormNode);
    // =>
    // {
    //   name: 'FreshHarvest Hub',
    //   shop: {
    //     name: 'Shop #1',
    //     isOpen: true,
    //   },
    // }
  })
</script>

HTMLFieldsetElement as array

getFormPayload/getFormControlPayload returns an array of objects when using the <fieldset> element and the [] symbol at the end of the name attribute of the <fieldset> elements. The functionality of recursively collecting values from nested <fieldset> elements is preserved.

<form name="company">
  <label>Company name: <input name="name" type="text" value="FreshHarvest Hub"></label>
  <fieldset name="shops[]">
    <label>Shop name: <input name="name" type="text" value="Shop #1"></label>
    <label>Open: <input name="isOpen" type="checkbox" checked></label>
  </fieldset>
  <fieldset name="shops[]">
    <label>Shop name: <input name="name" type="text" value="Shop #2"></label>
    <label>Open: <input name="isOpen" type="checkbox"></label>
  </fieldset>
  <button type="submit">Submit</button>
</form>

<script>
  import { getFormPayload } from 'form-payload';

  const { company: companyFormNode } = document.forms;

  companyFormNode.addEventListener('submit', (evt) => {
    evt.preventDefault();

    const formPayload = getFormPayload(companyFormNode);
    // =>
    // {
    //   name: 'FreshHarvest Hub',
    //   shops: [
    //     {
    //       name: 'Shop #1',
    //       isOpen: true,
    //     },
    //     {
    //       name: 'Shop #2',
    //       isOpen: false,
    //     },
    //   ],
    // }
  })
</script>

Inspired by FormData and Web-platform in general ♡.

form-payload's People

Contributors

ai avatar github-actions[bot] avatar what1s1ove avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

form-payload's Issues

Add more restrictions to ESLint

  • run eslint globaly
  • plugin:import/recommended
  • plugin:sonarjs/recommended
  • plugin:unicorn/recommended
  • simple-import-sort
  • eslint-plugin-perfectionist
  • custom rules

Cover uncovered areas with tests

  • Skipping benned control elements
  • Nesting
    <form>
      <input name="firstname" />
      <fieldset name="user">
        <input name="firstname" />
      </fieldset>
    </form>
  • remove useless wrappers
  • remove screen from testing library
  • update readme with lates api changes

Feature: Fieldset elements with same name and `[]` prefix should return an array of objects

Brief description

<form>
  <fieldset name="fruits[]">
    <input type="text" name="name" value="banana">
  <fieldset>
  <fieldset name="fruits[]">
    <input type="text" name="name" value="apple">
  <fieldset>
</form>
<script>
  const formPayload = getFormPayload(document.querySelector('form'))
  // => { fruits:  [{ name: 'banana' }, { name: 'apple' }] }
</script>

Freeform description field

No response

Bug: HTMLInput element with type="radio" returns inccorect value

The part of the code where the error occurred

<form name="shop">
  <label>Shop name: <input name="name" type="text" value="Shop #1"></label>
  <label>Apple <input name="fruit" type="radio" value="apple" checked></label>
  <label>Orange <input name="fruit" type="radio" value="orange"></label>
  <label>Banana <input name="fruit" type="radio" value="banana"></label>
  <button type="submit">Submit</button>
</form>

Description of the bug

Current result:

{
  name: 'Shop #1',
  fruit: 'banana',
}

Expected result

{
  name: 'Shop #1',
  fruit: 'apple', // checked input element
}

https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormControlsCollection

Bug: Build script

The part of the code where the error occurred

  "build": "npm run ci:build:clean && npm run ci:build:dist && npm run ci:build:pkg && npm run ci:build:cp"

Description of the bug

Should be

  "build": "npm run ci:build:clean && npm run ci:build:dist && npm run ci:build:pkg && npm run ci:build:cp"

Feature: Add advance usage to readme.md

Brief description

  • anti-examples to readme
    • "Upload CV" to Usage section
    • bad: const file = evt.target.files?.[0] ?? null;
    • better: const [file = null] = env.target.files ?? [];
    • ideal: const file = getFormControlPayload();
  • Advance examples
    • Rename demos to "js", "ts validator" and "framework"
    • fieldset element
    • fieldset with [] in name
    • checkbox with [] in name
  • Add lints from MDN to readme
    • Input types
  • Update all demos source code after new version release

Freeform description field

No response

Update readme

  • demo
    • Validation. Any can be used. const getFormPayload = (formNode, validation) => {}
  • Package Examples in readme.md
  • Control type - return value
    • skipped elements
    • table (element, isSkipped, attribute, value)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.