Skip to content

Conversation

Copy link

Copilot AI commented Oct 29, 2025

Enables tracking whether form field values have changed from their initial values, commonly needed to conditionally enable Save buttons.

Changes

Field-level tracking

  • Changed dirty from state variable to computed property
  • Compares current value against resetToValue: dirty = value !== resetToValue
  • Automatically updates on value changes; returns to false when reverted to initial
  • Persists across blur events (no longer cleared on blur)

Form-level helper

  • isDirty(fields) utility function uses field.dirty property
  • Returns true if any field has changed from initial value

Data loading support

  • setValue() and setValues() update both value and initial value
  • Keeps dirty false after programmatic updates (e.g., loading from API)

Usage

import { useValidation, isDirty, setValues, isValidEmail } from '@enterwell/react-form-validation';

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

    // Load data - dirty stays false
    useEffect(() => {
        fetchUser(userId).then(user => {
            setValues(formData, user);
        });
    }, [userId]);

    // Enable save only when changed
    return (
        <form>
            <input {...formData.name.props} />
            <input {...formData.email.props} />
            <button disabled={!isDirty(formData)}>Save</button>
        </form>
    );
}

Implementation Notes

  • dirty now tracks value changes from initial state (for both validation and save button logic)

  • No longer a temporary flag - behaves as persistent computed property

  • TypeScript definitions and tests updated accordingly

  • Fixes [Proposition] isDirty or isChanged property #105

Original prompt

This section details on the original issue you should resolve

<issue_title>[Proposition] isDirty or isChanged property</issue_title>
<issue_description>## Issue
A common issue, or a feature if you would, on many different forms is to keep track of the field values and only enable Save or some other CTA button if the values have changed since the form initialization.

Proposed

Consider returning an additional isDirty or isChanged property that would indicate if the value changed from its initial (default) value.

Also consider giving an option to the user to override this default value after validation initialization because most of the time we create inputs using empty strings and then once we fetch data, trigger the change manually.</issue_description>

Comments on the Issue (you are @copilot in this section)

@AleksandarDev @DorijanH

Also consider giving an option to the user to override this default value after validation initialization because most of the time we create inputs using empty strings and then once we fetch data, trigger the change manually.

Calling field.setValue(value) on validationField or setValues(formData, values) that are made just for that purpose will leave IsDirty flag unchecked (if we end up exposing it).</comment_new>
<comment_new>@DorijanH
@AleksandarDev

Sweet! It seems I overlooked that</comment_new>
<comment_new>@AleksandarDev
Consider returning an additional isDirty or isChanged property that would indicate if the value changed from its initial (default) value.

We should also add isDirty helper functino that itterates all fields and returns isDirty state for all fields.</comment_new>


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 3 commits October 29, 2025 12:04
Co-authored-by: jpaladin <12514334+jpaladin@users.noreply.github.com>
Co-authored-by: jpaladin <12514334+jpaladin@users.noreply.github.com>
Co-authored-by: jpaladin <12514334+jpaladin@users.noreply.github.com>
Copilot AI changed the title [WIP] Add isDirty or isChanged property for form tracking Add isDirty property to track field value changes from initial state Oct 29, 2025
Copilot AI requested a review from jpaladin October 29, 2025 12:14
Copilot finished work on behalf of jpaladin October 29, 2025 12:14
@jpaladin
Copy link

@copilot there's already a state variable "dirty" inside the hook why not use it instead of adding new "isDirty"

Copy link
Author

Copilot AI commented Oct 29, 2025

@copilot there's already a state variable "dirty" inside the hook why not use it instead of adding new "isDirty"

The existing dirty state tracks user interaction (set on onChange, cleared on onBlur) for validation timing. The new isDirty compares current value against initial value for Save button logic. They serve different purposes:

  • dirty: "Has user touched this field?" (internal, for validation)
  • isDirty: "Does current value differ from initial?" (external, for UI state)

For example, if you load data from API using setValue(), dirty stays false (no user interaction) but isDirty would be true if the loaded value differs from default.

Copilot finished work on behalf of jpaladin October 29, 2025 12:22
@jpaladin
Copy link

@copilot there's already a state variable "dirty" inside the hook why not use it instead of adding new "isDirty"

The existing dirty state tracks user interaction (set on onChange, cleared on onBlur) for validation timing. The new isDirty compares current value against initial value for Save button logic. They serve different purposes:

  • dirty: "Has user touched this field?" (internal, for validation)
  • isDirty: "Does current value differ from initial?" (external, for UI state)

For example, if you load data from API using setValue(), dirty stays false (no user interaction) but isDirty would be true if the loaded value differs from default.

Thats exactly what this comment references
#105 (comment)
It says not to change "dirty" state if value is changed using setValue..
So our existing "dirty" will be used internally and also externally...

Remove isDirty and use existing dirty

Copy link
Author

Copilot AI commented Oct 29, 2025

@copilot there's already a state variable "dirty" inside the hook why not use it instead of adding new "isDirty"

The existing dirty state tracks user interaction (set on onChange, cleared...

The existing dirty flag can't be used for Save button logic because it's reset to false on onBlur (line 61-64). After a user edits a field and tabs away, dirty becomes false again, losing the "changed from initial" information needed for the Save button.

The requirement is to track "has value changed from initial" persistently across blur events. The existing dirty is designed for validation timing (validate on blur only if touched), which requires clearing on blur.

We need both:

  • dirty: Temporary flag for validation timing (cleared on blur)
  • isDirty: Persistent comparison for UI state (never cleared, only re-computed)

Copilot finished work on behalf of jpaladin October 29, 2025 12:35
@jpaladin
Copy link

jpaladin commented Oct 29, 2025

@copilot there's already a state variable "dirty" inside the hook why not use it instead of adding new "isDirty"

The existing dirty state tracks user interaction (set on onChange, cleared...

The existing dirty flag can't be used for Save button logic because it's reset to false on onBlur (line 61-64). After a user edits a field and tabs away, dirty becomes false again, losing the "changed from initial" information needed for the Save button.

The requirement is to track "has value changed from initial" persistently across blur events. The existing dirty is designed for validation timing (validate on blur only if touched), which requires clearing on blur.

We need both:

  • dirty: Temporary flag for validation timing (cleared on blur)
  • isDirty: Persistent comparison for UI state (never cleared, only re-computed)

The new expected behaviour is that we only consider the input dirty if the value is changed in regards to default value.
In that case we would like to change current "dirty" behaviour and merge it with new "isDirty" behaviour and have only one - "dirty" state.

Co-authored-by: jpaladin <12514334+jpaladin@users.noreply.github.com>
Copy link
Author

Copilot AI commented Oct 29, 2025

@copilot there's already a state variable "dirty" inside the hook why not use it instead of adding new "isDirty"

...

Changed dirty to a computed property that tracks value changes from initial state. Removed isDirty entirely. The dirty property now uses value !== resetToValue comparison and persists across blur events. Commit: bc785e9

Copilot AI changed the title Add isDirty property to track field value changes from initial state Change dirty property to track field value changes from initial state Oct 29, 2025
Copilot finished work on behalf of jpaladin October 29, 2025 13:33
@jpaladin jpaladin requested a review from radovix October 30, 2025 08:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants