I am experimenting with multiple TextFields on a single widget and how to bring the controllers and the texts together. I thought that this approach worked out quite nicely:
import 'package:flutter/material.dart';
class TextExample extends StatefulWidget {
const TextExample({Key? key}) : super(key: key);
@override
_TextExampleState createState() => _TextExampleState();
}
class _TextExampleState extends State<TextExample> {
// A few strings and a few controllers
List<String> texts = ["", "", ""];
var controllers = [
TextEditingController(),
TextEditingController(),
TextEditingController(),
];
@override
Widget build(BuildContext context) {
// link the controllers to the text
for (var i = 0; i < controllers.length; i ) {
controllers[i].text = texts[i];
controllers[i].addListener(updateAllTexts);
}
return Scaffold(
appBar: AppBar(
title: Text("Text eingeben"),
),
body: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
children: [
// Display: Input fields and text
TextField( controller: controllers[0],),
Text(texts[0]),
TextField( controller: controllers[1],),
Text(texts[1]),
],
),
),
);
}
void updateAllTexts() {
setState(() {
for (var i = 0; i < controllers.length; i ) {
texts[i] = controllers[i].text;
}
});
}
}
I am running above code in Chrome. It works nicely until I use the mouse to switch between the text fields. It seems to happen with Tab as well, but not so reliably. Once it happens, it happens with every keypress. Apart from that, the app "works", i.e. the text of the input field is mirrored into the static Text.
The exception then is:
======== Exception caught by scheduler library =====================================================
The following TypeErrorImpl was thrown during a scheduler callback:
Unexpected null value.
When the exception was thrown, this was the stack:
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 236:49 throw_
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 518:63 nullCheck
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/semantics/text_field.dart 29:64 get instance
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/semantics/text_field.dart 364:45 update
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/semantics/semantics.dart 824:14 [_updateRole]
Is this related to my code, or is this a bug?
CodePudding user response:
Don't know of your error exactly but move out
for (var i = 0; i < controllers.length; i )
{ controllers[i].text = texts[i]; controllers[i].addListener(updateAllTexts); }
from inside the build method. Each time the widget rebuilds you are adding a new listener to each controller, which should not be what you want.
Probably move that block to initState
, and also override the dispose method to dispose all controllers.
void dispose(){
super.dispose();
for (var controller in controllers)
{ controller.dispose(); }
}