Skip to content

Commit 0e462e1

Browse files
fix(field): recompute isDirty when value matches initial
1 parent 38a24f6 commit 0e462e1

3 files changed

Lines changed: 74 additions & 1 deletion

File tree

lib/src/form_builder_field.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ class FormBuilderFieldState<F extends FormBuilderField<T>, T>
185185

186186
void _informFormForFieldChange() {
187187
if (_formBuilderState != null) {
188-
_dirty = true;
188+
_dirty = value != initialValue;
189189
if (enabled || readOnly) {
190190
_formBuilderState!.setInternalFieldValue<T>(widget.name, value);
191191
return;

test/src/form_builder_field_test.dart

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,27 @@ void main() {
419419
expect(textFieldKey.currentState?.isDirty, true);
420420
},
421421
);
422+
testWidgets('Should not dirty when value returns to initial by user', (
423+
tester,
424+
) async {
425+
const textFieldName = 'text';
426+
final textFieldKey = GlobalKey<FormBuilderFieldState>();
427+
final testWidget = FormBuilderTextField(
428+
name: textFieldName,
429+
key: textFieldKey,
430+
initialValue: 'hi',
431+
);
432+
await tester.pumpWidget(buildTestableFieldWidget(testWidget));
433+
434+
final widgetFinder = find.byWidget(testWidget);
435+
await tester.enterText(widgetFinder, 'test');
436+
await tester.pumpAndSettle();
437+
expect(textFieldKey.currentState?.isDirty, true);
438+
439+
await tester.enterText(widgetFinder, 'hi');
440+
await tester.pumpAndSettle();
441+
expect(textFieldKey.currentState?.isDirty, false);
442+
});
422443
testWidgets('Should not dirty when reset field value', (tester) async {
423444
const textFieldName = 'text';
424445
final textFieldKey = GlobalKey<FormBuilderFieldState>();
@@ -481,6 +502,37 @@ void main() {
481502
});
482503
});
483504
group('reset -', () {
505+
testWidgets(
506+
'Should avoid reset recursion when value returns to initial in onChanged',
507+
(tester) async {
508+
const textFieldName = 'text';
509+
final textFieldKey = GlobalKey<FormBuilderFieldState>();
510+
var onChangedCalls = 0;
511+
final testWidget = FormBuilderTextField(
512+
name: textFieldName,
513+
key: textFieldKey,
514+
initialValue: 'hi',
515+
onChanged: (value) {
516+
onChangedCalls++;
517+
final state = textFieldKey.currentState;
518+
if (value == state?.initialValue && state?.isDirty == true) {
519+
state?.reset();
520+
}
521+
},
522+
);
523+
await tester.pumpWidget(buildTestableFieldWidget(testWidget));
524+
525+
final widgetFinder = find.byWidget(testWidget);
526+
await tester.enterText(widgetFinder, 'test');
527+
await tester.pumpAndSettle();
528+
await tester.enterText(widgetFinder, 'hi');
529+
await tester.pumpAndSettle();
530+
531+
expect(tester.takeException(), isNull);
532+
expect(textFieldKey.currentState?.isDirty, false);
533+
expect(onChangedCalls, equals(2));
534+
},
535+
);
484536
testWidgets('Should reset to null when call reset', (tester) async {
485537
const textFieldName = 'text';
486538
final textFieldKey = GlobalKey<FormBuilderFieldState>();

test/src/form_builder_test.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,27 @@ void main() {
444444

445445
expect(formKey.currentState?.isDirty, true);
446446
});
447+
testWidgets('Should not dirty when value returns to initial by user', (
448+
tester,
449+
) async {
450+
const textFieldName = 'text';
451+
final testWidget = FormBuilderTextField(name: textFieldName);
452+
await tester.pumpWidget(
453+
buildTestableFieldWidget(
454+
testWidget,
455+
initialValue: {textFieldName: 'hi'},
456+
),
457+
);
458+
459+
final widgetFinder = find.byWidget(testWidget);
460+
await tester.enterText(widgetFinder, 'test');
461+
await tester.pumpAndSettle();
462+
expect(formKey.currentState?.isDirty, true);
463+
464+
await tester.enterText(widgetFinder, 'hi');
465+
await tester.pumpAndSettle();
466+
expect(formKey.currentState?.isDirty, false);
467+
});
447468
testWidgets('Should dirty when update field with initial value by method', (
448469
tester,
449470
) async {

0 commit comments

Comments
 (0)