Open
Description
Is there an existing issue for this?
- I have searched the existing issues
Package/Plugin version
10.0.0-dev.1
Platforms
- AndroidiOSLinuxMacOSWebWindows
Flutter doctor
Flutter doctor
[√] Flutter (Channel stable, 3.27.1, on Microsoft Windows [Version 10.0.26100.2605], locale en-US)
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
[√] Chrome - develop for the web
[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.10.4)
[√] Android Studio (version 2024.1)
[√] VS Code (version 1.96.2)
[√] Connected device (5 available)
[√] Network resources
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';
final RouteObserver<ModalRoute> routeObserver = RouteObserver<ModalRoute>();
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
navigatorObservers: [routeObserver],
home: FormScreen(),
);
}
}
class FormScreen extends StatefulWidget {
const FormScreen({super.key});
@override
State<FormScreen> createState() => _FormScreenState();
}
class _FormScreenState extends State<FormScreen> {
@override
Widget build(BuildContext context) {
// final size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Form Builder Example'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: SingleChildScrollView(
child: FormChild(),
),
),
);
}
}
class FormChild extends StatefulWidget {
const FormChild({super.key});
@override
State<FormChild> createState() => _FormChildState();
}
class _FormChildState extends State<FormChild> with ScopedGetItMixin {
final GlobalKey<FormBuilderState> _formBuilderKey = GlobalKey<FormBuilderState>();
AutovalidateMode _autovalidateMode = AutovalidateMode.disabled;
@override
Widget build(BuildContext context) {
return FormBuilder(
key: _formBuilderKey,
autovalidateMode: _autovalidateMode,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
spacing: 10.0,
children: [
// Submit button
ElevatedButton(
style: ButtonStyle(shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)))),
onPressed: () {
FocusManager.instance.primaryFocus?.unfocus();
},
child: const Text('Unfocus'),
),
ElevatedButton(
style: ButtonStyle(shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)))),
onPressed: () {
final result = _formBuilderKey.currentState?.saveAndValidate();
if(result != true && _autovalidateMode != AutovalidateMode.onUserInteraction){
setState(() {
_autovalidateMode = AutovalidateMode.onUserInteraction;
});
}
},
child: const Text('submit'),
),
ElevatedButton(
style: ButtonStyle(shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)))),
onPressed: () {
showModalBottomSheet(
context: context,
isScrollControlled: true,
showDragHandle: true,
builder: (context) {
return SizedBox(
height: 500,
width: 400,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
FormBuilderTextField(
name: 'textfield2',
decoration: const InputDecoration(
labelText: 'Enter text 1',
),
validator: FormBuilderValidators.required(),
)
],
),
);
},
);
},
child: Text("Open bottom sheet"),
),
],
),
),
// TextField 1
FormBuilderTextField(
name: 'textfield1',
decoration: const InputDecoration(
labelText: 'Enter text 1',
),
validator: FormBuilderValidators.required(),
),
const SizedBox(height: 20),
],
),
);
}
}
mixin ScopedGetItMixin<T extends StatefulWidget> on State<T> implements RouteAware {
@override
void didChangeDependencies() {
super.didChangeDependencies();
routeObserver.subscribe(this, ModalRoute.of(context)!);
}
@override
void dispose() {
super.dispose();
routeObserver.unsubscribe(this);
}
@override
void didPop() {
}
@override
void didPopNext() {
}
@override
void didPush() {
}
@override
void didPushNext() {
}
}
Current Behavior
I've developed a mixin called ScopedGetItMixin for use with StatefulWidget that contains a FormBuilder. However, I've noticed that after the form calls saveAndValidate, tapping a button to open a showModalBottomSheet causes a FormBuilderTextField to unexpectedly regain focus, triggering the keyboard to appear.
The main cause might be ScopedGetItMixin, but at the moment, I’m not sure why using ScopedGetItMixin results in this behavior.
Expected Behavior
I hope the focus behavior of FormBuilderTextField gets fixed.
Steps To Reproduce
I will describe it again through the video below.
focus_textfield1.mp4
Aditional information
No response
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Ready
Milestone
Relationships
Development
No branches or pull requests
Activity
quochuyR commentedon Jan 10, 2025
The second issue is related to the focus behavior of
FormBuilderTextField
.It’s not possible to unfocus the FormBuilderTextField when the field has an error, if the parent widget uses MediaQuery.of(context)
The behavior that causes the error is described in the video below.
focus_textfield2.mp4