flutterx_forms 1.3.4
flutterx_forms: ^1.3.4 copied to clipboard
Create, validate and manage all aspects of your forms in a new simple way. :D :D :D
example/lib/main.dart
import 'package:cross_file/cross_file.dart';
import 'package:flutter/material.dart' hide DialogRoute;
import 'package:flutterx_application/flutterx_application.dart';
import 'package:flutterx_application/flutterx_ui.dart';
import 'package:flutterx_forms/flutterx_forms.dart';
class Labels extends LabelInterface {
const Labels() : super(locale: const Locale('en', 'US'));
}
void main() => runApplication(
name: 'Flutterx Forms Demo',
initialize: (context) => MyApp.route,
locale: () => LocaleData(labels: {const Labels()}, onLabel: (_) {}),
routes: {MyApp.route},
theme: ThemeData());
class MyApp extends StatelessWidget {
static final ActivityRoute<void> route =
ActivityRoute(location: '/index', builder: (context, args) => const MyApp._());
const MyApp._();
@override
Widget build(BuildContext context) => MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutterx Forms Demo',
theme: ThemeData(primarySwatch: Colors.grey, useMaterial3: true).copyWith(
inputDecorationTheme: const InputDecorationTheme(
labelStyle: TextStyle(),
floatingLabelStyle: TextStyle(color: Colors.grey),
border: OutlineInputBorder(),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey, width: 2)))),
home: const FormsExample());
}
class FormsExample extends StatefulWidget {
const FormsExample({super.key});
@override
State<FormsExample> createState() => _FormsExampleState();
}
class _FormsExampleState extends State<FormsExample> with FormController {
late final XFormField<String> _name = field();
late final XFormField<String> _surname = field();
late final XFormField<int?> _age = field();
late final XFormField<double?> _x = field();
late final XFormField<XFile> _id = field();
late final XFormField<List<SampleOption>> _sampleOptions = field();
late final XFormField<List<String>> _tags = field();
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text('Forms example')),
body: ResponsiveScreenContent(
child: Card(
child: Padding(
padding: const EdgeInsets.all(m12),
child: buildForm(children: [
XTextFormField(
field: _name,
validator: nonEmpty(() => 'Field should not be empty'),
textInputAction: TextInputAction.next,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.words,
style: const TextStyle(fontSize: 16),
decoration: const InputDecoration(isDense: true, labelText: 'Nome', hintText: 'Giuseppe'),
autovalidateMode: AutovalidateMode.onUserInteraction),
const SizedBox(height: m12),
XTextFormField(
field: _surname,
validator: nonEmpty(() => 'Field should not be empty'),
textInputAction: TextInputAction.done,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.words,
style: const TextStyle(fontSize: 16),
decoration: const InputDecoration(isDense: true, labelText: 'Cognome', hintText: 'Simone'),
autovalidateMode: AutovalidateMode.onUserInteraction),
const SizedBox(height: m12),
XIntFormField(
field: _age,
initialValue: 34,
validator: validateFirst([
nonNull(() => 'Field should not be null'),
gte(18, () => 'Field must ve >=18'),
]),
textInputAction: TextInputAction.next,
decoration: const InputDecoration(isDense: true, labelText: 'Età', hintText: '18'),
autovalidateMode: AutovalidateMode.onUserInteraction),
const SizedBox(height: m12),
XDoubleFormField(
field: _x,
min: -2.24,
max: 56,
validator: validateFirst([
nonNull(() => 'Field should not be null'),
gte(3, () => 'Field must ve >=3'),
]),
textInputAction: TextInputAction.done,
arrows: const NumberFieldArrows(step: .5),
decoration: const InputDecoration(isDense: true, labelText: 'xyz', hintText: '0.4'),
autovalidateMode: AutovalidateMode.onUserInteraction),
const SizedBox(height: m12),
XSetFormField<SampleOption>(
field: _sampleOptions,
items: SampleOption.values,
initialValue: const {SampleOption.option2},
itemInitialValue: (items, _) => items.first,
itemBuilder: (state, field, initialValue, index, items) => XDropdownMenuFormField<SampleOption>(
field: field,
items: items,
initialValue: initialValue,
decoration: InputDecoration(
labelText: 'Options ${index + 1}', suffixIcon: const Icon(Icons.arrow_drop_down)),
validator: (item) => item == SampleOption.option2 ? null : 'Option 2 is only valid answer',
menuEntryBuilder: menuEntryByLabel((item) => item.name))),
const SizedBox(height: m12),
XTextListFormField(
field: _tags, decoration: const InputDecoration(isDense: true, labelText: 'Tags')),
const SizedBox(height: m12),
const SizedBox(height: m12),
// FileUploadFormField(
// key: _id.fieldKey,
// focusNode: _id.focusNode,
// validator: nonNull(message: 'Field id required').validator,
// decoration: const InputDecoration(
// isDense: true,
// labelText: 'Id',
// hintText: 'Upload',
// suffixIconConstraints:
// BoxConstraints(minHeight: 52, minWidth: kMinInteractiveDimension * 2)),
// autovalidateMode: AutovalidateMode.onUserInteraction),
])))),
floatingActionButton: FloatingActionButton(onPressed: submitForm, child: const Icon(Icons.add)));
@override
void onFormSubmit() {
DialogRoute(
location: '/result',
builder: (context, args) => AlertDialog(
actions: const [AlertDialogAction.positive()],
content: Text('Result: \n'
' name: ${_name.value}\n'
' surname: ${_surname.value}\n'
' age: ${_age.valueOrNull}\n'
' id: ${_id.valueOrNull?.name}\n'),
)).open(context);
}
}
enum SampleOption { option1, option2, option3 }