Hello,
I just upgraded flutter_form_bloc from version 0.10.0 to 0.12.2 and getting exceptions when calling submit. I noticed that this only happens when I have 3 or more TextFieldBlocBuilder
s on screen and updating their initial values. Then when I call submit, the app hangs for a few seconds and I see exceptions in the debug console:
E/flutter (15380): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Stack Overflow
E/flutter (15380): #0 new DiagnosticsProperty
package:flutter/โฆ/foundation/diagnostics.dart:2545
E/flutter (15380): #1 new _ErrorDiagnostic
package:flutter/โฆ/foundation/assertions.dart:31
E/flutter (15380): #2 new ErrorDescription
package:flutter/โฆ/foundation/assertions.dart:111
E/flutter (15380): #3 ChangeNotifier.notifyListeners
package:flutter/โฆ/foundation/change_notifier.dart:212
E/flutter (15380): #4 TextEditingController.selection=
package:flutter/โฆ/widgets/editable_text.dart:275
E/flutter (15380): #5 _TextFieldBlocBuilderState._fixControllerTextValue
package:flutter_form_bloc/src/text_field_bloc_builder.dart:730
E/flutter (15380): #6 _TextFieldBlocBuilderState._fixControllerTextValue (package:flutter_form_bloc/src/text_field_bloc_builder.dart)
E/flutter (15380): #7 _TextFieldBlocBuilderState._textControllerListener
package:flutter_form_bloc/src/text_field_bloc_builder.dart:713
E/flutter (15380): #8 ChangeNotifier.notifyListeners
package:flutter/โฆ/foundation/change_notifier.dart:206
E/flutter (15380): #9 _TextFieldBlocBuilderState._fixControllerTextValue
package:flutter_form_bloc/src/text_field_bloc_builder.dart:267
E/flutter (15380): #10 _TextFieldBlocBuilderState._fixControllerTextValue (package:flutter_form_bloc/src/text_field_bloc_builder.dart)
E/flutter (15380): #11 _TextFieldBlocBuilderState._textControllerListener
package:flutter_form_bloc/src/text_field_bloc_builder.dart:713
E/flutter (15380): #12 ChangeNotifier.notifyListeners
package:flutter/โฆ/foundation/change_notifier.dart:206
E/flutter (15380): #13 TextEditingController.selection=
package:flutter/โฆ/widgets/editable_text.dart:275
E/flutter (15380): #14 _TextFieldBlocBuilderState._fixControllerTextValue
package:flutter_form_bloc/src/text_field_bloc_builder.dart:730
E/flutter (15380): #15 _TextFieldBlocBuilderState._fixControllerTextValue (package:flutter_form_bloc/src/text_field_bloc_builder.dart)
Here's my Bloc:
class ClientFormBloc extends FormBloc<String, String> {
final ClientsRepository clientsRepository;
final Client client;
final name = TextFieldBloc(
validators: [CustomValidator.name],
);
final email = TextFieldBloc(
validators: [CustomValidator.emailOptional],
);
final phone = TextFieldBloc();
final website = TextFieldBloc();
final notes = TextFieldBloc();
ClientFormBloc({@required this.clientsRepository, @required this.client})
: super(autoValidate: false) {
if (client != null) {
name.updateInitialValue(client.name);
email.updateInitialValue(client.email);
phone.updateInitialValue(client.phone);
website.updateInitialValue(client.website);
notes.updateInitialValue(client.notes);
}
addFieldBlocs(fieldBlocs: [
name,
email,
country,
phone,
website,
notes,
]);
}
@override
void onSubmitting() async {
final clientUid = client != null ? client.uid : Uuid().v4();
final nameValue = name.value.parse();
final emailValue = email.value.parse();
final phoneValue = phone.value.parse();
final websiteValue = website.value.parse();
final notesValue = notes.value.parse();
final updatedClient = Client(
uid: clientUid,
name: nameValue,
email: emailValue,
phone: phoneValue,
website: websiteValue,
notes: notesValue);
clientsRepository.saveClient(updatedClient);
emitSuccess();
}
}
And the screen widget:
class ClientFormScreen extends StatefulWidget {
ClientFormScreen({key}) : super(key: key);
@override
_ClientFormScreenState createState() => _ClientFormScreenState();
}
class _ClientFormScreenState extends State<ClientFormScreen> {
@override
Widget build(BuildContext context) {
final Client client = ModalRoute.of(context).settings.arguments;
return BlocProvider<ClientFormBloc>(
create: (context) => ClientFormBloc(
clientsRepository: RepositoryProvider.of<ClientsRepository>(context),
client: client,
),
child: Builder(
builder: (context) {
final formBloc = context.bloc<ClientFormBloc>();
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(
Icons.close,
),
onPressed: Navigator.of(context).pop,
),
title: Text(
client == null
? tr('general.new_client')
: tr('general.edit_client'),
),
actions: <Widget>[
FlatButton(
onPressed: context.bloc<ClientFormBloc>().submit,
child: Text(
tr('general.save'),
style: TextStyle(
color: Theme.of(context).colorScheme.onPrimary),
),
),
],
),
body: FormBlocListener<ClientFormBloc, String, String>(
onSuccess: (context, state) {
Navigator.of(context).pop();
},
child: ListView(
children: <Widget>[
TextFieldBlocBuilder(
textFieldBloc: formBloc.name,
keyboardType: TextInputType.text,
decoration: InputDecoration(
border: OutlineInputBorder(),
icon: Icon(MaterialIcons.person_outline),
labelText: tr('general.name'),
),
),
TextFieldBlocBuilder(
textFieldBloc: formBloc.email,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
border: OutlineInputBorder(),
icon: Icon(MaterialIcons.mail_outline),
labelText: tr('general.email'),
),
),
TextFieldBlocBuilder(
textFieldBloc: formBloc.phone,
keyboardType: TextInputType.phone,
decoration: InputDecoration(
border: OutlineInputBorder(),
icon: Icon(MaterialIcons.phone),
labelText: tr('general.phone'),
),
),
TextFieldBlocBuilder(
textFieldBloc: formBloc.website,
keyboardType: TextInputType.url,
decoration: InputDecoration(
border: OutlineInputBorder(),
icon: Icon(MaterialIcons.public),
labelText: tr('general.website'),
),
),
TextFieldBlocBuilder(
textFieldBloc: formBloc.notes,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
border: OutlineInputBorder(),
icon: Icon(MaterialIcons.subject),
labelText: tr('general.notes'),
),
),
],
),
),
);
},
),
);
}
}
Is there anything I'm doing wrong? I didn't have any issues with the previous version.
Thanks