WIP adresscontroller validator

This commit is contained in:
Thomas Klein Langenhorst 2022-10-25 08:36:32 +02:00
parent 1b4d920586
commit affa510a5c
5 changed files with 187 additions and 145 deletions

View file

@ -31,20 +31,16 @@ class MyApp extends StatelessWidget {
} }
class AddressFormExample extends StatelessWidget { class AddressFormExample extends StatelessWidget {
AddressFormExample({Key? key}) : super(key: key); AddressFormExample({super.key});
final RegExp zipcodeRegExp = RegExp(r'^[1-9][0-9]{3}\s?[a-zA-Z]{2}$'); // final RegExp zipcodeRegExp = RegExp(r'^[1-9][0-9]{3}\s?[a-zA-Z]{2}$');
@override final _addressController = AddressController(
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: AddressForm(
zipCodeValidator: (text) { zipCodeValidator: (text) {
if (text.isEmpty) { if (text.isEmpty) {
return 'Can\'t be empty'; return 'Can\'t be empty';
} }
if (!zipcodeRegExp.hasMatch(text)) { if (!RegExp(r'^[1-9][0-9]{3}\s?[a-zA-Z]{2}$').hasMatch(text)) {
return 'Invalid zipcode'; return 'Invalid zipcode';
} }
return null; return null;
@ -70,15 +66,31 @@ class AddressFormExample extends StatelessWidget {
} }
return null; return null;
}, },
onAutoComplete: (address) {
return address;
},
cityValidator: (text) { cityValidator: (text) {
if (text.isEmpty) { if (text.isEmpty) {
return 'Can\'t be empty'; return 'Can\'t be empty';
} }
return null; return null;
}, },
controller: AddressController(onAutoComplete: (address) { );
return address;
}), @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
AddressForm(
onSubmit: (value) => value, controller: _addressController),
TextButton(
onPressed: () {
_addressController.validate;
},
child: Text('Test'))
],
), ),
); );
} }

View file

@ -1,3 +1,4 @@
library flutter_address_form; library flutter_address_form;
export 'src/address_form.dart'; export 'src/address_form.dart';
export 'src/models/address_model.dart';

View file

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:ffi';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -6,74 +7,74 @@ import 'package:flutter_address_form/src/models/address_model.dart';
/// A widget that creates a form with different address fields widgets. /// A widget that creates a form with different address fields widgets.
/// Returns a `AddressModel` Object from a `AddressController`. /// Returns a `AddressModel` Object from a `AddressController`.
class AddressForm extends StatelessWidget { class AddressForm extends StatefulWidget {
AddressForm({ AddressForm({
Key? key, super.key,
this.zipCodeLabel = const Text('Zipcode'),
this.housenumberLabel = const Text('Housenumber'),
this.suffixLabel = const Text('Suffix'),
this.streetLabel = const Text('Street'),
this.cityLabel = const Text('City'),
required this.zipCodeValidator,
required this.housenumberValidator,
required this.suffixValidator,
required this.streetValidator,
required this.cityValidator,
AddressController? controller, AddressController? controller,
this.zipCodeDecoration = const InputDecoration(label: Text('Zipcode')),
this.housenumberDecoration =
const InputDecoration(label: Text('Housenumber')),
this.suffixDecoration = const InputDecoration(label: Text('Suffix')),
this.streetDecoration = const InputDecoration(label: Text('Street')),
this.cityDecoration = const InputDecoration(label: Text('City')),
required this.onSubmit,
}) { }) {
_addressController = _addressController = controller ??
controller ?? AddressController(onAutoComplete: (model) => model); AddressController(
onAutoComplete: (model) => model,
zipCodeValidator: (text) => null,
cityValidator: (text) => null,
housenumberValidator: (text) => null,
streetValidator: (text) => null,
suffixValidator: (text) => null,
);
} }
final Widget zipCodeLabel; final InputDecoration zipCodeDecoration;
final Widget housenumberLabel; final InputDecoration housenumberDecoration;
final Widget suffixLabel; final InputDecoration suffixDecoration;
final Widget streetLabel; final InputDecoration streetDecoration;
final Widget cityLabel; final InputDecoration cityDecoration;
final String? Function(String) zipCodeValidator; final ValueChanged<String> onSubmit;
final String? Function(String) housenumberValidator;
final String? Function(String) suffixValidator;
final String? Function(String) streetValidator;
final String? Function(String) cityValidator;
/// Controls the `AddressModel` /// Controls the `AddressModel`
late final AddressController _addressController; late final AddressController _addressController;
@override
State<AddressForm> createState() => _AddressFormState();
}
class _AddressFormState extends State<AddressForm> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Column(
children: [ children: [
AddressFormTextField( AddressFormTextField(
controller: _addressController._zipcodeController, controller: widget._addressController._zipcodeController,
validator: zipCodeValidator, fieldDecoration: widget.zipCodeDecoration,
label: zipCodeLabel,
), ),
Flexible( Flexible(
child: Row( child: Row(
children: [ children: [
AddressFormTextField( AddressFormTextField(
controller: _addressController._housenumberController, controller: widget._addressController._housenumberController,
validator: housenumberValidator, fieldDecoration: widget.housenumberDecoration,
label: housenumberLabel,
), ),
AddressFormTextField( AddressFormTextField(
controller: _addressController._suffixController, controller: widget._addressController._suffixController,
validator: suffixValidator, fieldDecoration: widget.suffixDecoration,
label: suffixLabel,
), ),
], ],
), ),
), ),
AddressFormTextField( AddressFormTextField(
controller: _addressController._streetController, controller: widget._addressController._streetController,
validator: streetValidator, fieldDecoration: widget.streetDecoration,
label: streetLabel,
), ),
AddressFormTextField( AddressFormTextField(
controller: _addressController._cityController, controller: widget._addressController._cityController,
validator: cityValidator, fieldDecoration: widget.cityDecoration,
label: cityLabel,
), ),
], ],
); );
@ -81,17 +82,18 @@ class AddressForm extends StatelessWidget {
} }
class AddressFormTextField extends StatelessWidget { class AddressFormTextField extends StatelessWidget {
final Widget label; AddressFormTextField({
final TextEditingController controller; super.key,
final String? Function(String) validator; required this.fieldDecoration,
const AddressFormTextField({
Key? key,
required this.label,
required this.controller, required this.controller,
required this.validator, }) {
}) : super(key: key); _addressFieldDecoration = fieldDecoration;
}
String? get _errorText => validator(controller.value.text); final TextEditingController controller;
final InputDecoration fieldDecoration;
late final InputDecoration _addressFieldDecoration;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -103,14 +105,12 @@ class AddressFormTextField extends StatelessWidget {
margin: const EdgeInsets.all(10), margin: const EdgeInsets.all(10),
child: TextField( child: TextField(
controller: controller, controller: controller,
decoration: InputDecoration( decoration: _addressFieldDecoration,
label: label,
border: const OutlineInputBorder(),
errorText: _errorText),
), ),
), ),
); );
}); },
);
} }
} }
@ -121,7 +121,14 @@ class AddressController extends ChangeNotifier {
/// When the form changes, the function passes the current `AddressModel` as an argument and gives the possibility to manipulate and return a `AddressModel`. /// When the form changes, the function passes the current `AddressModel` as an argument and gives the possibility to manipulate and return a `AddressModel`.
final FutureOr<AddressModel> Function(AddressModel)? onAutoComplete; final FutureOr<AddressModel> Function(AddressModel)? onAutoComplete;
AddressController({this.initialValue, this.onAutoComplete}) { AddressController(
{this.initialValue,
this.onAutoComplete,
required this.zipCodeValidator,
required this.housenumberValidator,
required this.suffixValidator,
required this.streetValidator,
required this.cityValidator}) {
_model = initialValue ?? _model = initialValue ??
const AddressModel( const AddressModel(
zipcode: null, zipcode: null,
@ -140,6 +147,12 @@ class AddressController extends ChangeNotifier {
late AddressModel _model; late AddressModel _model;
final String? Function(String) zipCodeValidator;
final String? Function(String) housenumberValidator;
final String? Function(String) suffixValidator;
final String? Function(String) streetValidator;
final String? Function(String) cityValidator;
late final _zipcodeController = late final _zipcodeController =
TextEditingController(text: initialValue?.zipcode); TextEditingController(text: initialValue?.zipcode);
late final _streetController = late final _streetController =
@ -152,6 +165,20 @@ class AddressController extends ChangeNotifier {
AddressModel get model => _model; AddressModel get model => _model;
bool get validate => _validate();
bool _validate() {
if (zipCodeValidator.call(_zipcodeController.text) == null &&
streetValidator.call(_streetController.text) == null &&
housenumberValidator.call(_housenumberController.text) == null &&
suffixValidator.call(_suffixController.text) == null &&
cityValidator.call(_cityController.text) == null) {
return true;
} else {
return false;
}
}
void _update() async { void _update() async {
AddressModel updatedModel = _model.copyWith( AddressModel updatedModel = _model.copyWith(
zipcode: _zipcodeController.text, zipcode: _zipcodeController.text,

View file

@ -1,7 +1,6 @@
name: flutter_address_form name: flutter_address_form
description: A new Flutter package project. description: A new Flutter package project.
version: 0.0.1 version: 0.0.1
homepage:
environment: environment:
sdk: '>=2.18.2 <3.0.0' sdk: '>=2.18.2 <3.0.0'

View file

@ -11,6 +11,8 @@ void main() {
home: Scaffold( home: Scaffold(
appBar: AppBar(), appBar: AppBar(),
body: AddressForm( body: AddressForm(
onSubmit: (value) => value,
controller: AddressController(
zipCodeValidator: (text) { zipCodeValidator: (text) {
if (text.isEmpty) { if (text.isEmpty) {
return 'Can\'t be empty'; return 'Can\'t be empty';
@ -41,15 +43,16 @@ void main() {
} }
return null; return null;
}, },
onAutoComplete: (address) {
return address;
},
cityValidator: (text) { cityValidator: (text) {
if (text.isEmpty) { if (text.isEmpty) {
return 'Can\'t be empty'; return 'Can\'t be empty';
} }
return null; return null;
}, },
controller: AddressController(onAutoComplete: (address) { ),
return address;
}),
), ),
), ),
), ),