Skip to content
Merged

Stage #159

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4e6e674
Removed react-dom as peer dependency
AleksandarDev Sep 3, 2024
3da909d
Expose dirty flag for fields
AleksandarDev Sep 3, 2024
43b93b6
Switched to PNPM instead of yarn
AleksandarDev Sep 3, 2024
ad916ac
Updated vite and cypress packages
AleksandarDev Sep 3, 2024
4092317
Enable node corepack
AleksandarDev Sep 3, 2024
3af8399
Merge pull request #134 from Enterwell/feat/pnpm-instead-of-yarn
AleksandarDev Sep 3, 2024
ff4120f
Merge pull request #132 from Enterwell/feature/react-dom-removed-as-p…
AleksandarDev Dec 18, 2024
a65cc52
Merge pull request #135 from Enterwell/feat/updated-packages
AleksandarDev Dec 18, 2024
71fabac
Update README.md
radovix Dec 18, 2024
4e37ed0
Merge pull request #133 from Enterwell/feature/field-dirty-flag
AleksandarDev Dec 18, 2024
c1af963
Initial plan
Copilot Oct 29, 2025
1b453bd
Add isDirty property and helper function
Copilot Oct 29, 2025
fdef836
Update documentation for isDirty feature
Copilot Oct 29, 2025
a281dc9
Address code review feedback
Copilot Oct 29, 2025
bc785e9
Change dirty to computed property, remove isDirty
Copilot Oct 29, 2025
86f0ef5
Apply suggestion from @Copilot
jpaladin Feb 3, 2026
029b6c2
Apply suggestion from @Copilot
jpaladin Feb 3, 2026
3000dcd
Apply suggestion from @Copilot
jpaladin Feb 3, 2026
d3fe7c9
Apply suggestion from @Copilot
jpaladin Feb 3, 2026
c0b8498
removed unused state
joseph-ew Feb 3, 2026
5435698
fixed form data change loop
jpaladin Feb 3, 2026
3535641
Bump version from 1.5.0 to 1.6.0
jpaladin Feb 3, 2026
3289dca
Fixed tests hanging
jpaladin Feb 3, 2026
fb90e67
Merge pull request #158 from Enterwell/copilot/add-isdirty-property
AleksandarDev Feb 3, 2026
aa0fe63
chore: add pnpm workspace configuration to specify only built depende…
AleksandarDev Feb 3, 2026
dbd57b2
Refactor code structure for improved readability and maintainability
AleksandarDev Feb 3, 2026
9f01824
Wait for component mount using #empty_id in tests
AleksandarDev Feb 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- run: yarn install
- run: yarn build
- run: yarn test
node-version: 22
- name: Enable Corepack
run: corepack enable
- run: pnpm install
- run: pnpm build
- run: pnpm test
12 changes: 7 additions & 5 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
branches:
- master
paths:
- 'src/**'
- "src/**"

jobs:
buildAndPublish:
Expand All @@ -17,10 +17,12 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
node-version: 22
registry-url: "https://registry.npmjs.org"
- run: yarn install
- run: yarn build
- run: yarn publish
- name: Enable Corepack
run: corepack enable
- run: pnpm install
- run: pnpm build
- run: pnpm publish
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
8 changes: 2 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
Expand Down Expand Up @@ -51,12 +49,10 @@ typings/
# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# Dist and cypress folder
dist
cypress/videos
cypress/videos
cypress/screenshots
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v22.14.0
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [1.5.0] - 2024-09-03

### Added

- Field exposes `dirty` flag that indicates if the field has been changed

## [1.4.0] - 2023-12-19

### Added
Expand Down
File renamed without changes.
54 changes: 52 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

* Keeps form's state and validation results
* Supports any kind of validation functions
* Dirty checking
* Dirty checking (tracks value changes from initial state)
* Separates data from view
* Relies on hooks, but can easily be used with class components

Expand Down Expand Up @@ -87,7 +87,7 @@ Hook that keeps on form field's data.

| Type <div style="width: 200px"></div> | Description |
|---- | ----------- |
| _{<br>&nbsp;&nbsp;&nbsp;value: any,<br>&nbsp;&nbsp;&nbsp;error: boolean<br>&nbsp;&nbsp;&nbsp;onChange: (any, config?) => void<br>&nbsp;&nbsp;&nbsp;onBlur: (event, config?) => void<br>&nbsp;&nbsp;&nbsp;setValue: (value: any) => void<br>&nbsp;&nbsp;&nbsp;validate: (any, config?) => boolean or Promise&lt;boolean&gt;<br>&nbsp;&nbsp;&nbsp;reset: () => void,<br>&nbsp;&nbsp;&nbsp;props: {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value: any,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onChange: (any, config?) => void<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onBlur: (event, config?) => void<br>&nbsp;&nbsp;&nbsp;}<br>}_ | Object with field's data and callbacks.<br><br><ul><li>`value` - field's current value</li><li>`error` - is error present flag (`true` if value was validated and didn't pass validation, `false` otherwise)</li><li>`onChange` - callback for change event (changes the value and validates it if previous value wasn't correct)</li><li>`onBlur` - callback for blur event (validates the value)</li><li>`setValue` - function for setting the internal value (does not validate the input, enabling support for async data loading)</li><li>`validate` - function for validating field's value</li><li>`reset` - function for resetting field's data</li><li>`props` - set of props that can be spread on standard input elements (same as props in root object, just grouped for better DX)</li></ul><br/>`onChange`, `onBlur` and `validate` functions accept config as last parameter - this will override config from `useValidation` if provided. |
| _{<br>&nbsp;&nbsp;&nbsp;value: any,<br>&nbsp;&nbsp;&nbsp;error: boolean<br>&nbsp;&nbsp;&nbsp;dirty: boolean,<br>&nbsp;&nbsp;&nbsp;onChange: (any, config?) => void<br>&nbsp;&nbsp;&nbsp;onBlur: (event, config?) => void<br>&nbsp;&nbsp;&nbsp;setValue: (value: any) => void<br>&nbsp;&nbsp;&nbsp;validate: (any, config?) => boolean or Promise&lt;boolean&gt;<br>&nbsp;&nbsp;&nbsp;reset: () => void,<br>&nbsp;&nbsp;&nbsp;props: {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value: any,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onChange: (any, config?) => void<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onBlur: (event, config?) => void<br>&nbsp;&nbsp;&nbsp;}<br>}_ | Object with field's data and callbacks.<br><br><ul><li>`value` - field's current value</li><li>`error` - is error present flag (`true` if value was validated and didn't pass validation, `false` otherwise)</li><li>`dirty` - indicates whether current value differs from initial value (useful for enabling Save buttons and tracking changes)</li><li>`onChange` - callback for change event (changes the value and validates it if previous value wasn't correct)</li><li>`onBlur` - callback for blur event (validates the value)</li><li>`setValue` - function for setting the internal value (does not validate the input, enabling support for async data loading; also updates the initial value so `dirty` remains `false`)</li><li>`validate` - function for validating field's value</li><li>`reset` - function for resetting field's data</li><li>`props` - set of props that can be spread on standard input elements (same as props in root object, just grouped for better DX)</li></ul><br/>`onChange`, `onBlur` and `validate` functions accept config as last parameter - this will override config from `useValidation` if provided. |

#### Usage example

Expand Down Expand Up @@ -263,6 +263,56 @@ const onCancel = (data) => alert("Form has been reset");
cancelForm(userFormData, onCancel);
```

### `isDirty(fields)`

Util function for checking if any field in a form has been changed from its initial value. This is useful for enabling/disabling Save buttons based on whether the user has made any changes.

> **Note:** The dirty flag is determined using strict equality (`===`). For complex data types like objects or arrays, only changes to the reference will be detected—not changes to their internal structure. If you mutate an object or array in place, the dirty flag may not update as expected. This is similar to the limitation described for the `areEqual` validation function.
#### Params

| Name | Type <div style="width: 200px"></div> | Required | Description |
| ---- | ---- | ---- | ----------- |
| fields | _{<br/>&nbsp;&nbsp;key: { dirty: boolean },<br/>&nbsp;&nbsp;...<br/>}_ | yes | Form field's data (each field must have `dirty` property - other properties are not important) |

#### Returns

| Type <div style="width: 200px"></div> | Description |
|---- | ----------- |
| _boolean_ | `true` if any field has been changed from its initial value, `false` otherwise |

#### Usage example

```jsx
import { ..., isDirty } from '@enterwell/react-form-validation';

/* useValidation example's code... */

const formData = {
name: useValidation('', isNonEmptyString),
email: useValidation('', isValidEmail)
};

// Load data from API
useEffect(() => {
if (item) {
setValues(formData, {
name: item.name,
email: item.email
});
}
}, [item]);

// Check if form has changes
const hasChanges = isDirty(formData);

return (
<div>
{/* Form inputs */}
<button disabled={!hasChanges}>Save</button>
</div>
);
```

___

_Unless otherwise stated, each validation function will have the following #### Params and #### Returns._
Expand Down
Loading
Loading