I have two widgets - one is the main page with tabs and buttons and the second one is - Page with some TextFields. I would like to clean all TextFields after the button click. I tried to use
GlobalKey<_Page1> _key = GlobalKey<_Page1>();
and _key.currentState!.CleanAll();
but I received an error - Unhandled Exception: Null check operator used on a null value
Do you have any other ideas on how to do this?
class MyTabs extends StatefulWidget {
const MyTabs({Key? key}) : super(key: key);
@override
_MyTabsState createState() => _MyTabsState();
}
class _MyTabsState extends State<MyTabs> {
@override
Widget build(BuildContext context) {
return Column(
children: [
DefaultTabController(
length: 1, // length of tabs
initialIndex: 0,
child: Column(
children: <Widget>[
const TabBar(
labelColor: Colors.green,
unselectedLabelColor: Colors.blueGrey,
tabs: [
Tab(text: 'Page 1'),
],
),
SizedBox(
height: 200,
child: TabBarView(
children: <Widget>[
Page1(),
]
),
),
],
),),
ElevatedButton(
onPressed: () {
// <- clean all TextField in Page1
},
child: Text('Clean')
),
],
);
}
}
class Page1 extends StatefulWidget {
const Page1({Key? key}) : super(key: key);
@override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
TextEditingController text1 = TextEditingController();
TextEditingController text2 = TextEditingController();
void CleanAll() {
text1.clear();
text2.clear();
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: text1,
),
TextField(
controller: text2,
),
],
);
}
}
CodePudding user response:
You can use a ValueNotifier
that will listen on Page1
. then we will override initState on Page1
and clear the controlles.
class _MyTabsState extends State<MyTabs> {
final ValueNotifier<bool> clearNotifier = ValueNotifier(false);
pass it to the Page1
Page1(
clearCallback: clearNotifier,
),
to notify the listener we are just switching the value. bool value does not matter, we just need to update it.
onPressed: () {
clearNotifier.value = !clearNotifier.value;
},
and on Page1
class Page1 extends StatefulWidget {
final ValueNotifier clearCallback;
const Page1({Key? key, required this.clearCallback}) : super(key: key);
@override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
@override
void initState() {
super.initState();
widget.clearCallback.addListener(() {
CleanAll();
});
}
Test snippet
class MyTabs extends StatefulWidget {
const MyTabs({Key? key}) : super(key: key);
@override
_MyTabsState createState() => _MyTabsState();
}
class _MyTabsState extends State<MyTabs> {
final ValueNotifier<bool> clearNotifier = ValueNotifier(false);
@override
Widget build(BuildContext context) {
return Column(
children: [
DefaultTabController(
length: 1, // length of tabs
initialIndex: 0,
child: Column(
children: <Widget>[
const TabBar(
labelColor: Colors.green,
unselectedLabelColor: Colors.blueGrey,
tabs: [
Tab(text: 'Page 1'),
],
),
SizedBox(
height: 200,
child: TabBarView(children: <Widget>[
Page1(
clearCallback: clearNotifier,
),
]),
),
],
),
),
ElevatedButton(
onPressed: () {
clearNotifier.value = !clearNotifier.value;
},
child: Text('Clean')),
],
);
}
}
class Page1 extends StatefulWidget {
final ValueNotifier clearCallback;
const Page1({Key? key, required this.clearCallback}) : super(key: key);
@override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
@override
void initState() {
super.initState();
widget.clearCallback.addListener(() {
CleanAll();
});
}
TextEditingController text1 = TextEditingController();
TextEditingController text2 = TextEditingController();
void CleanAll() {
text1.clear();
text2.clear();
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: text1,
),
TextField(
controller: text2,
),
],
);
}
}