|
| 1 | +# Migrate from Legacy form2js |
| 2 | + |
| 3 | +If you built around the old single `form2js` script or the archived jQuery plugin flow, the main change is that modern form2js is now a small package family. You install only the part you need instead of pulling one browser-era bundle into every environment. |
| 4 | + |
| 5 | +The legacy code and historical examples still live in the [legacy branch](https://github.com/maxatwork/form2js/tree/legacy), but new work should move to the current packages and docs. |
| 6 | + |
| 7 | +## Quick Chooser |
| 8 | + |
| 9 | +| If your legacy code does this | Use now | Notes | |
| 10 | +| --- | --- | --- | |
| 11 | +| `form2js(form)` in the browser | [`@form2js/dom`](api-dom.md) | Closest direct replacement. Exports both `formToObject()` and a compatibility `form2js()` wrapper. | |
| 12 | +| `$("#form").toObject()` in jQuery | [`@form2js/jquery`](api-jquery.md) | Keeps the plugin shape while using the modern DOM parser underneath. | |
| 13 | +| Parse `FormData` on the server or in browser pipelines | [`@form2js/form-data`](api-form-data.md) | Best fit for fetch actions, loaders, workers, and Node. | |
| 14 | +| Handle submit state in React | [`@form2js/react`](api-react.md) | Wraps form parsing in a hook with async submit state and optional schema validation. | |
| 15 | +| Push object data back into a form | [`@form2js/js2form`](api-js2form.md) | Modern replacement for the old "object back into fields" helpers around the ecosystem. | |
| 16 | +| Work directly with path/value entries | [`@form2js/core`](api-core.md) | Lowest-level parser and formatter. | |
| 17 | + |
| 18 | +## What Changed |
| 19 | + |
| 20 | +- The archived project exposed one browser-oriented `form2js(rootNode, delimiter, skipEmpty, nodeCallback, useIdIfEmptyName)` entry point. |
| 21 | +- The current project splits that behavior by environment and responsibility. |
| 22 | +- Browser DOM extraction lives in `@form2js/dom`. |
| 23 | +- jQuery compatibility lives in `@form2js/jquery`. |
| 24 | +- `FormData`, React, object-to-form, and low-level entry parsing each have their own package. |
| 25 | + |
| 26 | +That split is the point of the rewrite: smaller installs, clearer environment boundaries, and first-class TypeScript/ESM support without making every user drag along legacy browser assumptions. |
| 27 | + |
| 28 | +## Legacy API Mapping |
| 29 | + |
| 30 | +Legacy browser code usually looked like this: |
| 31 | + |
| 32 | +```js |
| 33 | +var data = form2js(rootNode, ".", true, nodeCallback, false); |
| 34 | +``` |
| 35 | + |
| 36 | +Modern browser code should usually look like this: |
| 37 | + |
| 38 | +```ts |
| 39 | +import { formToObject } from "@form2js/dom"; |
| 40 | + |
| 41 | +const data = formToObject(rootNode, { |
| 42 | + delimiter: ".", |
| 43 | + skipEmpty: true, |
| 44 | + nodeCallback, |
| 45 | + useIdIfEmptyName: false |
| 46 | +}); |
| 47 | +``` |
| 48 | + |
| 49 | +If you want the smallest possible migration diff, `@form2js/dom` also exports a compatibility wrapper: |
| 50 | + |
| 51 | +```ts |
| 52 | +import { form2js } from "@form2js/dom"; |
| 53 | + |
| 54 | +const data = form2js(rootNode, ".", true, nodeCallback, false); |
| 55 | +``` |
| 56 | + |
| 57 | +Parameter mapping: |
| 58 | + |
| 59 | +| Legacy parameter | Modern equivalent | |
| 60 | +| --- | --- | |
| 61 | +| `rootNode` | `rootNode` | |
| 62 | +| `delimiter` | `options.delimiter` | |
| 63 | +| `skipEmpty` | `options.skipEmpty` | |
| 64 | +| `nodeCallback` | `options.nodeCallback` | |
| 65 | +| `useIdIfEmptyName` | `options.useIdIfEmptyName` | |
| 66 | + |
| 67 | +The main migration decision is not the parameter mapping. It is choosing the right package for the environment where parsing now happens. |
| 68 | + |
| 69 | +## Browser Migration |
| 70 | + |
| 71 | +For plain browser forms, install `@form2js/dom`: |
| 72 | + |
| 73 | +```bash |
| 74 | +npm install @form2js/dom |
| 75 | +``` |
| 76 | + |
| 77 | +Module usage: |
| 78 | + |
| 79 | +```ts |
| 80 | +import { formToObject } from "@form2js/dom"; |
| 81 | + |
| 82 | +const data = formToObject(document.getElementById("profileForm")); |
| 83 | +``` |
| 84 | + |
| 85 | +Standalone usage is still available for the DOM package: |
| 86 | + |
| 87 | +```html |
| 88 | +<script src="https://unpkg.com/@form2js/dom/dist/standalone.global.js"></script> |
| 89 | +<script> |
| 90 | + const data = formToObject(document.getElementById("profileForm")); |
| 91 | + // or form2js(document.getElementById("profileForm")) |
| 92 | +</script> |
| 93 | +``` |
| 94 | + |
| 95 | +## jQuery Migration |
| 96 | + |
| 97 | +If your codebase still expects `$.fn.toObject()`, move to `@form2js/jquery` instead of rebuilding that glue yourself. |
| 98 | + |
| 99 | +```bash |
| 100 | +npm install @form2js/jquery jquery |
| 101 | +``` |
| 102 | + |
| 103 | +```ts |
| 104 | +import $ from "jquery"; |
| 105 | +import { installToObjectPlugin } from "@form2js/jquery"; |
| 106 | + |
| 107 | +installToObjectPlugin($); |
| 108 | + |
| 109 | +const data = $("#profileForm").toObject({ mode: "first" }); |
| 110 | +``` |
| 111 | + |
| 112 | +Standalone usage is also available: |
| 113 | + |
| 114 | +```html |
| 115 | +<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> |
| 116 | +<script src="https://unpkg.com/@form2js/jquery/dist/standalone.global.js"></script> |
| 117 | +<script> |
| 118 | + const data = $("#profileForm").toObject({ mode: "combine" }); |
| 119 | +</script> |
| 120 | +``` |
| 121 | + |
| 122 | +## Behavior Differences To Check |
| 123 | + |
| 124 | +- `skipEmpty` still defaults to `true`, so empty strings and `null` values are skipped unless you opt out. |
| 125 | +- Disabled controls are ignored by default. Set `getDisabled: true` only if you really want them parsed. |
| 126 | +- Unsafe path segments such as `__proto__`, `prototype`, and `constructor` are rejected by default in the modern parser. |
| 127 | +- Only `@form2js/dom` and `@form2js/jquery` ship standalone browser globals. The other packages are module-only. |
| 128 | +- React and `FormData` use cases now have dedicated packages instead of being squeezed through the DOM entry point. |
| 129 | + |
| 130 | +## Where To Go Now |
| 131 | + |
| 132 | +If the legacy code used browser DOM access only because that was the only option at the time, this is the modern package map: |
| 133 | + |
| 134 | +- Use [`@form2js/form-data`](api-form-data.md) when your app already has `FormData`, request entries, or server-side action handlers. |
| 135 | +- Use [`@form2js/react`](api-react.md) when you want submit-state handling around parsing in React. |
| 136 | +- Use [`@form2js/js2form`](api-js2form.md) when you need to populate forms from nested objects. |
| 137 | +- Use [`@form2js/core`](api-core.md) when you already have raw key/value pairs and just need the parser rules. |
| 138 | + |
| 139 | +## Migration Checklist |
| 140 | + |
| 141 | +1. Identify whether the old code is DOM-based, jQuery-based, React-based, or really just `FormData` processing. |
| 142 | +2. Swap the legacy package or script include for the specific current package. |
| 143 | +3. Move old positional arguments to an options object where appropriate. |
| 144 | +4. Re-test any custom `nodeCallback` logic and any flows that depend on disabled or empty fields. |
| 145 | +5. Replace browser-only parsing with `@form2js/form-data` or `@form2js/react` when the parsing no longer needs direct DOM traversal. |
0 commit comments