Home > Blockchain >  How to set TextFormFields and Controllers in dynamics Cards using Listview builder
How to set TextFormFields and Controllers in dynamics Cards using Listview builder

Time:09-17

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.1st cardafter pressing button text is erasing

 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'),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

  • Related