Created
October 20, 2020 17:26
-
-
Save danqulogy/a53405fb4e3b1d97cf5a4ea371a886dd to your computer and use it in GitHub Desktop.
Add & Remove TextFormFields dynamically in Flutter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'package:flutter/material.dart'; | |
| void main() { | |
| runApp(MyApp()); | |
| } | |
| class MyApp extends StatelessWidget { | |
| @override | |
| Widget build(BuildContext context) { | |
| return MaterialApp( | |
| title: 'Dynamic TextFormFields', | |
| theme: ThemeData( | |
| primarySwatch: Colors.blue, | |
| visualDensity: VisualDensity.adaptivePlatformDensity, | |
| ), | |
| home: MyForm(), | |
| debugShowCheckedModeBanner: false, | |
| ); | |
| } | |
| } | |
| class MyForm extends StatefulWidget { | |
| @override | |
| _MyFormState createState() => _MyFormState(); | |
| } | |
| class _MyFormState extends State<MyForm> { | |
| final _formKey = GlobalKey<FormState>(); | |
| TextEditingController _nameController; | |
| static List<String> friendsList = [null]; | |
| @override | |
| void initState() { | |
| super.initState(); | |
| _nameController = TextEditingController(); | |
| } | |
| @override | |
| void dispose() { | |
| _nameController.dispose(); | |
| super.dispose(); | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| return Scaffold( | |
| backgroundColor: Colors.grey[200], | |
| appBar: AppBar(title: Text('Dynamic TextFormFields'),), | |
| body: Form( | |
| key: _formKey, | |
| child: Padding( | |
| padding: const EdgeInsets.all(16.0), | |
| child: Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: [ | |
| // name textfield | |
| Padding( | |
| padding: const EdgeInsets.only(right: 32.0), | |
| child: TextFormField( | |
| controller: _nameController, | |
| decoration: InputDecoration( | |
| hintText: 'Enter your name' | |
| ), | |
| validator: (v){ | |
| if(v.trim().isEmpty) return 'Please enter something'; | |
| return null; | |
| }, | |
| ), | |
| ), | |
| SizedBox(height: 20,), | |
| Text('Add Friends', style: TextStyle(fontWeight: FontWeight.w700, fontSize: 16),), | |
| ..._getFriends(), | |
| SizedBox(height: 40,), | |
| FlatButton( | |
| onPressed: (){ | |
| if(_formKey.currentState.validate()){ | |
| _formKey.currentState.save(); | |
| } | |
| }, | |
| child: Text('Submit'), | |
| color: Colors.green, | |
| ), | |
| ], | |
| ), | |
| ), | |
| ), | |
| ); | |
| } | |
| /// get firends text-fields | |
| List<Widget> _getFriends(){ | |
| List<Widget> friendsTextFields = []; | |
| for(int i=0; i<friendsList.length; i++){ | |
| friendsTextFields.add( | |
| Padding( | |
| padding: const EdgeInsets.symmetric(vertical: 16.0), | |
| child: Row( | |
| children: [ | |
| Expanded(child: FriendTextFields(i)), | |
| SizedBox(width: 16,), | |
| // we need add button at last friends row | |
| _addRemoveButton(i == friendsList.length-1, i), | |
| ], | |
| ), | |
| ) | |
| ); | |
| } | |
| return friendsTextFields; | |
| } | |
| /// add / remove button | |
| Widget _addRemoveButton(bool add, int index){ | |
| return InkWell( | |
| onTap: (){ | |
| if(add){ | |
| // add new text-fields at the top of all friends textfields | |
| friendsList.insert(0, null); | |
| } | |
| else friendsList.removeAt(index); | |
| setState((){}); | |
| }, | |
| child: Container( | |
| width: 30, | |
| height: 30, | |
| decoration: BoxDecoration( | |
| color: (add) ? Colors.green : Colors.red, | |
| borderRadius: BorderRadius.circular(20), | |
| ), | |
| child: Icon((add) ? Icons.add : Icons.remove, color: Colors.white,), | |
| ), | |
| ); | |
| } | |
| } | |
| class FriendTextFields extends StatefulWidget { | |
| final int index; | |
| FriendTextFields(this.index); | |
| @override | |
| _FriendTextFieldsState createState() => _FriendTextFieldsState(); | |
| } | |
| class _FriendTextFieldsState extends State<FriendTextFields> { | |
| TextEditingController _nameController; | |
| @override | |
| void initState() { | |
| super.initState(); | |
| _nameController = TextEditingController(); | |
| } | |
| @override | |
| void dispose() { | |
| _nameController.dispose(); | |
| super.dispose(); | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| WidgetsBinding.instance.addPostFrameCallback((timeStamp) { | |
| _nameController.text = _MyFormState.friendsList[widget.index] ?? ''; | |
| }); | |
| return TextFormField( | |
| controller: _nameController, | |
| onChanged: (v) => _MyFormState.friendsList[widget.index] = v, | |
| decoration: InputDecoration( | |
| hintText: 'Enter your friend\'s name' | |
| ), | |
| validator: (v){ | |
| if(v.trim().isEmpty) return 'Please enter something'; | |
| return null; | |
| }, | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment