Skip to content

Conversation

@yeleibo
Copy link

@yeleibo yeleibo commented Mar 21, 2023

fixes #123009

code sample ```
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(useMaterial3: true),
      home: Example(),
    );
  }
}

class Example extends StatelessWidget {
  final _formKey = GlobalKey<FormState>();
  Example({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Form(
          key: _formKey,
          child: Column(
            children: [
              CupertinoTextFormFieldRow(onChanged: (value) {
                print("CupertinoTextFormFieldRow widget onChange execute");
              }),
              TextFormField(onChanged: (value) {
                print("TextFormField widget onChange execute");
              }),
              DropdownButtonFormField(
                items: const [
                  DropdownMenuItem(
                    value: "item1",
                    child: Text("item1"),
                  )
                ],
                onChanged: (value) {
                  print("DropdownButtonFormField widget onChange execute");
                },
              ),
              ElevatedButton(
                  onPressed: () {
                    _formKey.currentState?.reset();
                  },
                  child: const Text("reset")),
            ],
          )),
    );
  }
}

…ieldRow widget reset function

Fix the implementation of FormField components: TextFormField, DropdownButtonFormField, and CupertinoTextFormFieldRow. Address the issue where their onChange() method does not get executed when the parent Form component calls reset().
@flutter-dashboard flutter-dashboard bot added a: text input Entering text in a text field or keyboard related problems f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. labels Mar 21, 2023
@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat (don't just cc him here, he won't see it! He's on Discord!).

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@google-cla
Copy link

google-cla bot commented Mar 21, 2023

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@yeleibo yeleibo changed the title change TextFormField, DropdownButtonFormField, and CupertinoTextFormF… Fix the implementation of FormField components: TextFormField, DropdownButtonFormField, and CupertinoTextFormFieldRow. Address the issue where their onChange() method does not get executed when the parent Form component calls reset() Mar 21, 2023
@yeleibo yeleibo changed the title Fix the implementation of FormField components: TextFormField, DropdownButtonFormField, and CupertinoTextFormFieldRow. Address the issue where their onChange() method does not get executed when the parent Form component calls reset() Fix FormField implementation components TextFormField, DropdownButtonFormField, CupertinoTextFormFieldRow. The problem that their onChange() method cannot be executed when the parent Form component calls the reset() method Mar 21, 2023
Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Are you able to add a test for this?

}
_cupertinoTextFormFieldRow.onChanged?.call(_effectiveController!.text);


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Too many newlines here.

@yeleibo
Copy link
Author

yeleibo commented Apr 25, 2023

Thanks for the PR! Are you able to add a test for this?
Yes, tests have been added.
The Linux docs_test action check is not passing, but I'm not sure why.

Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding the tests! I think the docs failures have to do with macros that don't exist. I commented about that below.

/// initialize its [TextEditingController.text] with [initialValue].
final TextEditingController? controller;

/// {@macro flutter.material.TextField.onChanged}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This macro doesn't exist, did you mean flutter.material.editableText.onChanged? Or you could create this macro if you want the entire TextField.onChanged docs.

/// initialize its [TextEditingController.text] with [initialValue].
final TextEditingController? controller;

/// {@macro flutter.material.CupertinoFormRow.onChanged}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This macro also doesn't seem to exist.

testWidgets('CupertinoTextFormFieldRow onChanged to initialValue when Form reset', (WidgetTester tester) async {
final GlobalKey<FormFieldState<String>> stateKey = GlobalKey<FormFieldState<String>>();
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String value='initialValue';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
String value='initialValue';
String value = 'initialValue';

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And anywhere else you're not spacing this out needs to have spaces too.

@justinmc
Copy link
Contributor

justinmc commented May 8, 2023

Looks like there are still docs test failures, it mentions [onSubmitted].

@yeleibo
Copy link
Author

yeleibo commented May 11, 2023

Looks like there are still docs test failures, it mentions [onSubmitted].

I used {@macro flutter.widgets.editableText.onChanged} in the comment of the onChanged property of a TextFormFieldRow. However, {@template flutter.widgets.editableText.onChanged} references the onSubmitted property of its own widget (which is indicated in the comment as [onSubmitted]), while my widget does not have an onSubmitted property, so the docs failures
image

Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly nits here. Thanks for getting all of the checks to pass.


/// Called when the user initiates a change to the TextField's
/// value: when they have inserted or deleted text or form reset.
final ValueChanged<String>? onChanged;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Add a newline after this.


/// Called when the user initiates a change to the TextField's
/// value: when they have inserted or deleted text or form reset.
final ValueChanged<String>? onChanged;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Newline here too.

await tester.enterText(find.byType(CupertinoTextField), 'changedValue');
expect(stateKey.currentState!.value,'changedValue');
expect(value, 'changedValue');
// form to reset
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to: "Reset form."


expect(value, isNull);
expect(stateKey.currentState!.value, equals('One'));
//value chang to Two
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Change value to "Two".

await tester.pumpAndSettle();
expect(value, equals('Two'));
expect(stateKey.currentState!.value, equals('Two'));
// form to reset
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Reset form.

await tester.enterText(find.byType(TextField), 'changedValue');
expect(stateKey.currentState!.value,'changedValue');
expect(value, 'changedValue');
// form to reset
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Reset form."


expect(stateKey.currentState!.value, 'initialValue');
expect(value, 'initialValue');
//change value to 'changedValue'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Change value to "changedValue".

_effectiveController!.text = widget.initialValue!;
});
}
_cupertinoTextFormFieldRow.onChanged?.call(_effectiveController!.text);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the value didn't actually change, should onChanged still be called?

final DropdownButtonFormField<T> dropdownButtonFormField = widget as DropdownButtonFormField<T>;
assert(dropdownButtonFormField.onChanged != null);
dropdownButtonFormField.onChanged!(widget.initialValue);
super.reset();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In CupertinoTextFormFieldRow, reset calls super on the first line. Should this one also call it on the first line?

// manipulated, no setState call is needed here.
_effectiveController.text = widget.initialValue ?? '';
_textFormField.onChanged?.call(_effectiveController.text);
super.reset();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this one calls super on the last line again. Not sure which is right 🤷 .

Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly nits here. Thanks for getting all of the checks to pass.

@Hixie
Copy link
Contributor

Hixie commented Jul 18, 2023

@yeleibo Thanks for the contribution! Will you be able to continue working on this? It's totally fine if not; we can take it over (though it might take longer). I'm just asking because I'm trying to clean out our review queue.

@bleroux
Copy link
Contributor

bleroux commented Sep 8, 2023

Closing this PR because I filed #134295 based on the work done here.
Thanks @yeleibo for initiating this work!

@bleroux bleroux closed this Sep 8, 2023
auto-submit bot pushed a commit that referenced this pull request Sep 21, 2023
## Description

This PR fixes form fields in order to call the `onChange` callback when the form is reset.

This change is based on the work done in #123108.

I considered adding the `onChange` callback to the `FormField` superclass but it would break existing code because two of the three subclasses defines the `onChange` callback with `ValueChanged<String>?` type and the third one defines it with `ValueChanged<String?>?`. 

## Related Issue

Fixes #123009.

## Tests

Adds 3 tests.
Mairramer pushed a commit to Mairramer/flutter that referenced this pull request Oct 10, 2023
## Description

This PR fixes form fields in order to call the `onChange` callback when the form is reset.

This change is based on the work done in flutter#123108.

I considered adding the `onChange` callback to the `FormField` superclass but it would break existing code because two of the three subclasses defines the `onChange` callback with `ValueChanged<String>?` type and the third one defines it with `ValueChanged<String?>?`. 

## Related Issue

Fixes flutter#123009.

## Tests

Adds 3 tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: text input Entering text in a text field or keyboard related problems f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

4 participants