flutterdartflutter-dependenciesflutter-form-builder

Multiple widgets used the same GlobalKey with FormBuilder


The following minimally reproducible dummy code throws this error:

════════ Exception caught by widgets library ═══════════════════════════════════
Multiple widgets used the same GlobalKey.
════════════════════════════════════════════════════════════════════════════════
Restarted application in 987ms.
I/flutter (10106): Key: [LabeledGlobalKey<FormBuilderState>#070c0 GlobalFormKey #SignIn ]

════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown while finalizing the widget tree:
Multiple widgets used the same GlobalKey.

The key [LabeledGlobalKey<FormBuilderState>#070c0 GlobalFormKey #SignIn ] was used by multiple widgets. The parents of those widgets were:
- FormBuilderWrapper-[LabeledGlobalKey<FormBuilderState>#070c0 GlobalFormKey #SignIn ]
- _BodyBuilder
A GlobalKey can only be specified on one widget at a time in the widget tree.

Dummy Code:

class SignInScreen extends StatelessWidget {
  final GlobalKey<FormBuilderState> key =
      GlobalKey<FormBuilderState>(debugLabel: 'GlobalFormKey #SignIn ');

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Dummy")),
      body: FormBuilderWrapper(
        key: key,
        childrenInColumn: [
          FormBuilderEmail(),
          FormBuilderPassword(identifierForField: "password")
        ],
      ),
    );
  }
}

class FormBuilderWrapper extends StatelessWidget {
  final List<Widget> childrenInColumn;
  final Key key;
  const FormBuilderWrapper({
    @required this.key,
    @required this.childrenInColumn,
  });
  @override
  Widget build(BuildContext context) {
    print("Key: $key");
    return FormBuilder(
      key: key,
      child: Column(
        children: this.childrenInColumn,
      ),
    );
  }
}

import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';

class FormBuilderEmail extends StatelessWidget {
  const FormBuilderEmail({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FormBuilderTextField(
      name: "email",
    );
  }
}
class FormBuilderPassword extends StatelessWidget {
  final String hintText;
  final String identifierForField;

  const FormBuilderPassword({
    @required this.identifierForField,
    this.hintText = "Password",
  });

  @override
  Widget build(BuildContext context) {
    return FormBuilderTextField(
      name: identifierForField,
    );
  }
}

What I don't understand is that only 1 widget uses the Key and that's the FormBuilder widget(I didn't count 'FormBuilderWrapper' as it merely passes the key to FormBuilder)

Can anyone point me in the right direction as to why this is happening? An explanation of which are the "multiple widgets" using the same GlobalKey would be great


Solution

  • I got it why you were getting the error. It was because of this statement. It is recognizing variable name key as keyword key.

     final GlobalKey<FormBuilderState> key =
          GlobalKey<FormBuilderState>(debugLabel: 'GlobalFormKey #SignIn ');
    

    Below is the modified version of the dummy code you uploaded. I didn't get any errors after execution but please check at your end.

        import 'package:flutter/material.dart';
        import 'package:flutter_form_builder/flutter_form_builder.dart';
        
        class SignInScreen extends StatelessWidget {
      final GlobalKey<FormBuilderState> _formkey =
          GlobalKey<FormBuilderState>(debugLabel: 'GlobalFormKey #SignIn ');
    
          @override
          Widget build(BuildContext context) {
            return Scaffold(
              appBar: AppBar(title: Text("Dummy")),
              body: FormBuilderWrapper(
                fomrkey: _formkey,
                childrenInColumn: [
                  FormBuilderEmail(),
                  FormBuilderPassword(identifierForField: "password")
                ],
              ),
            );
          }
        }
        
        class FormBuilderWrapper extends StatelessWidget {
          final List<Widget> childrenInColumn;
          final Key fomrkey;
          const FormBuilderWrapper({
            required this.fomrkey,
            required this.childrenInColumn,
          });
          @override
          Widget build(BuildContext context) {
            print("Key: $fomrkey");
            return FormBuilder(
              key: fomrkey,
              child: Column(
                children: this.childrenInColumn,
              ),
            );
          }
        }
        
        class FormBuilderEmail extends StatelessWidget {
          const FormBuilderEmail({
            Key? fomrkey1,
          }) : super(key: fomrkey1);
        
          @override
          Widget build(BuildContext context) {
            return FormBuilderTextField(
              name: "email",
            );
          }
        }
        
        class FormBuilderPassword extends StatelessWidget {
          final String hintText;
          final String identifierForField;
        
          const FormBuilderPassword({
            required this.identifierForField,
            this.hintText = "Password",
          });
        
          @override
          Widget build(BuildContext context) {
            return FormBuilderTextField(
              name: identifierForField,
            );
          }
        }