'Duplicate GlobalKey detected in widget tree Flutter
I have a list view which has a card as a child of list view. The card contains a TextFormField with a form key. Since it is a listview it builds the card multiple times with the same form key so it is giving error:
Duplicate GlobalKey detected in widget tree.
Please help me with this.
This is my code.
final GlobalKey<FormState> _formKey =
new GlobalKey<FormState>(debugLabel: ' _formKey');
@override
Widget build(BuildContext context) {
return Card(
margin: EdgeInsets.symmetric(
horizontal: 15,
vertical: 4,
),
child: Padding(
padding: EdgeInsets.all(8),
child: Column(
children: <Widget>[
ListTile(
leading: CircleAvatar(
backgroundColor: Colors.blue,
child: Padding(
padding: EdgeInsets.all(5),
child: FittedBox(
child: Text(
widget.price,
style: TextStyle(color: Colors.white),
),
),
),
),
title: Text('Title'),
subtitle: Text('Subtitle'),
trailing: Text(widget.quantity.toString() + ' x'),
),
Padding(
padding: const EdgeInsets.only(
left: 32, right: 5, top: 0, bottom: 5),
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Form(
key: this._formKey,
child: new TextFormField(
decoration: new InputDecoration(
hintText: 'Add your comments',
labelText: 'Comments'),
// validator: this._validateEmail,
onSaved: (String value) {
// _formKey.currentState.save();
},
),
),
],
),
))
}
Solution 1:[1]
You can copy paste run full test code below
You can use List<GlobalKey<FormState>> and generate key via data list length
code snippet
List<GlobalKey<FormState>> _formKey = [];
...
@override
void initState() {
// TODO: implement initState
_formKey = new List<GlobalKey<FormState>>.generate(dataList.length,
(i) => new GlobalKey<FormState>(debugLabel: ' _formKey'));
super.initState();
}
...
new Form(
key: this._formKey[index],
working demo
full test code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
appBarTheme: AppBarTheme(color: Colors.green),
primarySwatch: Colors.purple,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class Data {
String price;
int quantity;
Data({this.price, this.quantity});
}
class _MyHomePageState extends State<MyHomePage> {
List<Data> dataList = [
Data(price: "1", quantity: 2),
Data(price: "3", quantity: 4)
];
List<GlobalKey<FormState>> _formKey = [];
@override
void initState() {
// TODO: implement initState
_formKey = new List<GlobalKey<FormState>>.generate(dataList.length,
(i) => new GlobalKey<FormState>(debugLabel: ' _formKey'));
super.initState();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Simple Card view'),
),
body: new ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: dataList.length,
itemBuilder: (context, index) {
return Card(
margin: EdgeInsets.symmetric(
horizontal: 15,
vertical: 4,
),
child: Padding(
padding: EdgeInsets.all(8),
child: Column(children: <Widget>[
ListTile(
leading: CircleAvatar(
backgroundColor: Colors.blue,
child: Padding(
padding: EdgeInsets.all(5),
child: FittedBox(
child: Text(
dataList[index].price,
style: TextStyle(color: Colors.white),
),
),
),
),
title: Text('Title'),
subtitle: Text('Subtitle'),
trailing:
Text(dataList[index].quantity.toString() + ' x'),
),
Padding(
padding: const EdgeInsets.only(
left: 32, right: 5, top: 0, bottom: 5),
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Form(
key: this._formKey[index],
child: new TextFormField(
decoration: new InputDecoration(
hintText: 'Add your comments',
labelText: 'Comments'),
// validator: this._validateEmail,
onSaved: (String value) {
// _formKey.currentState.save();
},
),
),
],
),
))
])));
}));
}
}
Solution 2:[2]
For people wondering why given solution(s) are not working for them:
In my case I was using dependency injection, where I forgot to register (lazy) singletons to provide in my widgets.
So I was using GetIt with BLoC and did not register the bloc, event, state, etc.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | chunhunghan |
| Solution 2 | Levi Roelofsma |

