Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[General]: using isValid with multiple required form fields makes typing "jump" to latest invalid field #1253

Closed
1 task done
ManuelRauber opened this issue May 17, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@ManuelRauber
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Package/Plugin version

9.0.0

Flutter doctor

Flutter doctor
[✓] Flutter (Channel stable, 3.10.0, on macOS 13.3.1 22E772610a darwin-arm64, locale en-DE)
    • Flutter version 3.10.0 on channel stable at /opt/homebrew/Caskroom/flutter/3.10.0/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 84a1e904f4 (8 days ago), 2023-05-09 07:41:44 -0700
    • Engine revision d44b5a94c9
    • Dart version 3.0.0
    • DevTools version 2.23.1

[!] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
    • Android SDK at /Users/manuelrauber/Library/Android/sdk
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.

[✓] Xcode - develop for iOS and macOS (Xcode 14.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14E222b
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.2)
    • Android Studio at /Users/manuelrauber/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/222.4459.24.2221.9971841/Android
      Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)

[✓] Connected device (5 available)
<redacted>

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 1 category.

Minimal code example

Code sample
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';

void main() {
  runApp(const FlutterExample());
}

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: TheForm(),
    );
  }
}

class TheForm extends StatefulWidget {
  final formKey = GlobalKey<FormBuilderState>();

  TheForm({super.key});

  @override
  State<StatefulWidget> createState() => _TheFormState();
}

class _TheFormState extends State<TheForm> {
  bool _isValid = false;

  InputDecoration _defaultInputDecoration(String placeholder) =>
      InputDecoration(
          labelText: placeholder, border: const UnderlineInputBorder());

  @override
  Widget build(BuildContext context) => FormBuilder(
        key: widget.formKey,
        autovalidateMode: AutovalidateMode.onUserInteraction,
        onChanged: () {
          setState(() {
            _isValid = widget.formKey.currentState!.isValid;
          });
        },
        child: Scaffold(
          body: SafeArea(
            child: Column(
              children: [
                FormBuilderTextField(
                  name: 'name',
                  decoration: _defaultInputDecoration('Name'),
                  validator: FormBuilderValidators.required(),
                ),
                FormBuilderTextField(
                  name: 'email',
                  decoration: _defaultInputDecoration('E-Mail'),
                  validator: FormBuilderValidators.compose([
                    FormBuilderValidators.required(),
                    FormBuilderValidators.email()
                  ]),
                ),
                Visibility(
                  visible: true, // custom logic in my real code
                  child: FormBuilderTextField(
                    name: 'emailVerification',
                    decoration: _defaultInputDecoration('Repeat e-mail'),
                    validator: FormBuilderValidators.compose([
                      FormBuilderValidators.required(),
                      FormBuilderValidators.email()
                    ]),
                  ),
                ),
                Text(_isValid ? 'is valid' : 'is not valid'),
              ],
            ),
          ),
        ),
      );
}

Current Behavior

If I select the first text field (which is "Name") and I type one character the whole form shows being invalid and the focus jumps to the last field showing an error.

If you remove the validators from the last field, it will jump to the second one (which then is the last field showing an error) instead.

Instead of the Text I will have a button later than is either enabled/disabled depending on the state.

In addition (I can make a second issue for that, if you want): Using setState() shows all other form fields as error as well, even if there was no user input.

Expected Behavior

  • I expect that the focus stays within the same text field
  • I expect not all form fields showing an error without an user interaction

Steps To Reproduce

Run the example code and simply type something into the first text field.

Aditional information

I've used the idea of #1157 to check if the form is valid or not. I'm not sure if that is the correct approach because there is no documentation or example for isValid available.

Video of the issue:
https://github.com/flutter-form-builder-ecosystem/flutter_form_builder/assets/740791/2342681e-a793-49dd-81ae-e3a7b4b5a33c

@ManuelRauber ManuelRauber added the bug Something isn't working label May 17, 2023
@ManuelRauber
Copy link
Author

In addition (I can make a second issue for that, if you want): Using setState() shows all other form fields as error as well, even if there was no user input.

I may solved this one by removing autovalidateMode: AutovalidateMode.onUserInteraction on the form and put it on the formFields instead.

It may also solve the "jumping" around.

@uragecz
Copy link

uragecz commented May 16, 2024

This leads me to a question, why the validation is trying to focus last invalid input instead of first ?? I am having validation only on submit. But when there are more invalid fields, the latest is focused. In my example its DatePicker, and its very annoying when onsubmit opens DatePicker (if its empty). Is there some way to start focusing fields from top ??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants