Created
April 4, 2024 18:04
-
-
Save austinn/842e5debb272200408a0f4637f34095d to your computer and use it in GitHub Desktop.
Basic Flutter List Form
This file contains 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
// Copyright 2019 the Dart project authors. All rights reserved. | |
// Use of this source code is governed by a BSD-style license | |
// that can be found in the LICENSE file. | |
import 'package:flutter/material.dart'; | |
import 'package:flutter_hooks/flutter_hooks.dart'; | |
import 'package:hooks_riverpod/hooks_riverpod.dart'; | |
void main() => runApp(const MyApp()); | |
class MyApp extends StatelessWidget { | |
const MyApp({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Flutter Demo', | |
debugShowCheckedModeBanner: false, | |
theme: ThemeData( | |
primarySwatch: Colors.blue, | |
), | |
home: Scaffold(body: const HomeScreen()), | |
); | |
} | |
} | |
class FormData { | |
String? name; | |
String? email; | |
bool? enable; | |
FormData({this.name, this.email, this.enable}); | |
} | |
class HomeScreen extends StatefulHookConsumerWidget { | |
static const name = 'home'; | |
static const path = '/home'; | |
const HomeScreen({super.key}); | |
@override | |
ConsumerState<HomeScreen> createState() => _HomeScreenState(); | |
} | |
class _HomeScreenState extends ConsumerState<HomeScreen> { | |
// List to store form data | |
List<FormData> formsData = []; | |
List<GlobalKey<FormState>> formKeys = []; | |
@override | |
void initState() { | |
super.initState(); | |
for (int i = 0; i < 3; i++) { | |
formsData.add(FormData()); | |
formKeys.add(GlobalKey<FormState>()); | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
return SingleChildScrollView( | |
child: Padding( | |
padding: const EdgeInsets.all(16.0), | |
child: Column( | |
children: [ | |
ListView.builder( | |
shrinkWrap: true, | |
physics: const NeverScrollableScrollPhysics(), | |
itemCount: formsData.length, | |
itemBuilder: (context, index) { | |
return CheckboxListTile( | |
onChanged: null, | |
title: Text('Name: ${formsData[index].name}'), | |
subtitle: Text('Email: ${formsData[index].email}'), | |
value: formsData[index].enable ?? false, | |
); | |
}, | |
), | |
const SizedBox(height: 16), | |
ListView.separated( | |
shrinkWrap: true, | |
physics: const NeverScrollableScrollPhysics(), | |
itemCount: formsData.length, | |
separatorBuilder: (context, index) { | |
return const SizedBox(height: 16.0); | |
}, | |
itemBuilder: (context, index) { | |
final data = formsData[index]; | |
final key = formKeys[index]; | |
return FormCard( | |
formKey: key, | |
formData: data, | |
); | |
}, | |
), | |
const SizedBox(height: 16.0), | |
ElevatedButton( | |
onPressed: () { | |
for (int i = 0; i < formsData.length; i++) { | |
final formKey = formKeys[i]; | |
final form = formKey.currentState; | |
if (form != null && form.validate()) { | |
setState(() { | |
form.save(); | |
}); | |
} | |
} | |
}, | |
child: const Text('Submit'), | |
), | |
], | |
), | |
), | |
); | |
} | |
} | |
class FormCard extends StatefulHookWidget { | |
const FormCard({ | |
super.key, | |
required this.formKey, | |
required this.formData, | |
}); | |
final GlobalKey<FormState> formKey; | |
final FormData formData; | |
@override | |
State<FormCard> createState() => _FormCardState(); | |
} | |
class _FormCardState extends State<FormCard> { | |
@override | |
Widget build(BuildContext context) { | |
final nameController = useTextEditingController(); | |
final emailController = useTextEditingController(); | |
return Card( | |
child: Padding( | |
padding: const EdgeInsets.all(16.0), | |
child: Form( | |
key: widget.formKey, | |
child: Column( | |
children: [ | |
TextFormField( | |
controller: nameController, | |
decoration: const InputDecoration(labelText: 'Name'), | |
validator: (value) { | |
if (value == null || value.isEmpty) { | |
return 'Please enter name'; | |
} | |
return null; | |
}, | |
onSaved: (value) { | |
print('Saving name: $value'); | |
widget.formData.name = value; | |
}, | |
), | |
const SizedBox(height: 8.0), | |
TextFormField( | |
controller: emailController, | |
decoration: const InputDecoration(labelText: 'Email'), | |
validator: (value) { | |
if (value == null || value.isEmpty) { | |
return 'Please enter email'; | |
} | |
return null; | |
}, | |
onSaved: (value) { | |
print('Saving email: $value'); | |
widget.formData.email = value; | |
}, | |
), | |
const SizedBox(height: 8.0), | |
CheckboxListTile( | |
title: const Text('Enable'), | |
value: widget.formData.enable ?? false, | |
onChanged: (value) { | |
setState(() { | |
widget.formData.enable = value; | |
}); | |
}, | |
), | |
], | |
), | |
), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment