I am trying to build each Card with textformfields when the button is pressed, until it reaches some limit like 10 cards only, So when I pressed the floating button, Card is adding but text in textformfields is erasing for every press. Can anyone help me to build Cards dynamically with textformfields without erasing for every press? Below I am attaching screenshots of app.
import 'package:flutter/material.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CardWithTextformfield(),
);
}
}
class CardWithTextformfield extends StatefulWidget {
const CardWithTextformfield({Key? key}) : super(key: key);
@override
_CardWithTextformfieldState createState() => _CardWithTextformfieldState();
}
class _CardWithTextformfieldState extends State<CardWithTextformfield> {
var name =<TextEditingController>[];
var id =<TextEditingController>[];
var addCard =0;
void incrementcard(){
setState(() {
if(addCard >=7){
return;
}
addCard ;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Card with TextformField'),
),
floatingActionButton: FloatingActionButton(
onPressed: incrementcard,
child: Icon(Icons.add),
),
body: Container(
child:ListView.builder(
itemCount: addCard,
itemBuilder: (context,index){
return cardslist();
}
),
),
);
}
Widget cardslist(){
var nameController = TextEditingController();
var idController = TextEditingController();
name.add(nameController);
id.add(idController);
return Card(
margin: EdgeInsets.all(10),
child: Container(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
margin: EdgeInsets.all(10),
child: Text('Name: ')),
Expanded(child: TextFormField(
controller: nameController,
decoration: InputDecoration(hintText: 'Name'),
),),
Container(
margin: EdgeInsets.all(10),
child: Text('EmpId: '),),
Expanded(child: TextFormField(
controller: idController,
decoration: InputDecoration(hintText: 'EmpId'),
),),
],
),
],
),
),
);
}
}
CodePudding user response:
The problem with your approach is that you re-create every controller when a new card is inserted, that's why the entered values are lost. Instead you should check for whether controllers already exist in your array for the current card, and if yes, use the existing controllers, otherwise create a new ones.
To do so, you have to add index
as a parameter to your cardsList
method. The code below I think will solve your problem.
Important: controllers should be destroyed when this widget is destroyed, please add that part. You should override dispose
method in your _CardWithTextformfieldState
, loop through all of your controllers in both arrays, and call dispose()
on every controller. At the end do not forget to call super.dispose()
.
import 'package:flutter/material.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CardWithTextformfield(),
);
}
}
class CardWithTextformfield extends StatefulWidget {
const CardWithTextformfield({Key? key}) : super(key: key);
@override
_CardWithTextformfieldState createState() => _CardWithTextformfieldState();
}
class _CardWithTextformfieldState extends State<CardWithTextformfield> {
final _name = <TextEditingController>[];
final _id = <TextEditingController>[];
int _addCard = 0;
void _incrementcard() {
setState(() {
if (_addCard >= 7) {
return;
}
_addCard ;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Card with TextformField'),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementcard,
child: Icon(Icons.add),
),
body: Container(
child: ListView.builder(
itemCount: _addCard,
itemBuilder: (context, index) {
return cardslist(index);
}),
),
);
}
Widget cardslist(int index) {
if (_name.length <= index) {
_name.add(TextEditingController());
_id.add(TextEditingController());
}
return Card(
margin: EdgeInsets.all(10),
child: Container(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(margin: EdgeInsets.all(10), child: Text('Name: ')),
Expanded(
child: TextFormField(
controller: _name[index],
decoration: InputDecoration(hintText: 'Name'),
),
),
Container(
margin: EdgeInsets.all(10),
child: Text('EmpId: '),
),
Expanded(
child: TextFormField(
controller: _id[index],
decoration: InputDecoration(hintText: 'EmpId'),
),
),
],
),
],
),
),
);
}
}