mirror of
https://github.com/Iconica-Development/flutter_address_form.git
synced 2025-05-19 10:43:45 +02:00
Added simple validators
This commit is contained in:
parent
9b7cbf4d69
commit
38b0e0801c
3 changed files with 179 additions and 48 deletions
13
lib/src/address_controller.dart
Normal file
13
lib/src/address_controller.dart
Normal file
|
@ -0,0 +1,13 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class AddressController extends ChangeNotifier {
|
||||
final String zipcode;
|
||||
final int houseNumber;
|
||||
final String prefix;
|
||||
final String street;
|
||||
final String city;
|
||||
|
||||
AddressController(this.zipcode, this.houseNumber, this.prefix, this.street, this.city);
|
||||
|
||||
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_address_form/src/models/address.dart';
|
||||
|
||||
class AddressForm extends StatefulWidget {
|
||||
AddressForm({Key? key}) : super(key: key);
|
||||
const AddressForm({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<AddressForm> createState() => _AddressFormState();
|
||||
|
@ -10,58 +10,146 @@ class AddressForm extends StatefulWidget {
|
|||
|
||||
class _AddressFormState extends State<AddressForm> {
|
||||
final TextEditingController _zipcodeController = TextEditingController();
|
||||
final TextEditingController _houseNumberController = TextEditingController();
|
||||
final TextEditingController _prefixController = TextEditingController();
|
||||
final TextEditingController _streetController = TextEditingController();
|
||||
final TextEditingController _cityController = TextEditingController();
|
||||
|
||||
final RegExp _zipcodeRegExp = RegExp(r'^[1-9][0-9]{3}\s?[a-zA-Z]{2}$');
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Form(
|
||||
child: Column(
|
||||
return Column(
|
||||
children: [
|
||||
_createField(
|
||||
label: 'Postcode',
|
||||
AddressFormTextField(
|
||||
controller: _zipcodeController,
|
||||
validator: (text) {
|
||||
if (text.isEmpty) {
|
||||
return 'Can\'t be empty';
|
||||
}
|
||||
if (!_zipcodeRegExp.hasMatch(text)) {
|
||||
return 'Invalid zipcode';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
label: 'Postcode',
|
||||
),
|
||||
Flexible(
|
||||
child: Row(
|
||||
children: [
|
||||
_createField(
|
||||
AddressFormTextField(
|
||||
controller: _houseNumberController,
|
||||
validator: (text) {
|
||||
if (text.isEmpty) {
|
||||
return 'Can\'t be empty';
|
||||
}
|
||||
if (text.length >= 3 || int.tryParse(text) == null) {
|
||||
return 'Invalid number';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
label: 'Huisnummer',
|
||||
controller: TextEditingController(),
|
||||
),
|
||||
_createField(
|
||||
AddressFormTextField(
|
||||
controller: _prefixController,
|
||||
validator: (text) {
|
||||
if (text.isEmpty) {
|
||||
return 'Can\'t be empty';
|
||||
}
|
||||
if (RegExp(r'/^[a-z]*$/').hasMatch(text) &&
|
||||
text.length != 1) {
|
||||
return 'Invalid prefix';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
label: 'Toevoeging',
|
||||
controller: TextEditingController(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
_createField(
|
||||
AddressFormTextField(
|
||||
controller: _streetController,
|
||||
validator: (text) {
|
||||
if (text.isEmpty) {
|
||||
return 'Can\'t be empty';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
label: 'Straatnaam',
|
||||
controller: TextEditingController(),
|
||||
),
|
||||
_createField(
|
||||
AddressFormTextField(
|
||||
controller: _cityController,
|
||||
validator: (text) {
|
||||
if (text.isEmpty) {
|
||||
return 'Can\'t be empty';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
label: 'Woonplaats',
|
||||
controller: TextEditingController(),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
child: Text('Test'),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _createField(
|
||||
{required String label, required TextEditingController controller}) {
|
||||
@override
|
||||
void dispose() {
|
||||
_zipcodeController.dispose();
|
||||
_houseNumberController.dispose();
|
||||
_prefixController.dispose();
|
||||
_streetController.dispose();
|
||||
_cityController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class AddressFormTextField extends StatefulWidget {
|
||||
final String label;
|
||||
final TextEditingController controller;
|
||||
final String? Function(String) validator;
|
||||
AddressFormTextField({
|
||||
Key? key,
|
||||
required this.label,
|
||||
required this.controller,
|
||||
required this.validator,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<AddressFormTextField> createState() => _AddressFormTextFieldState();
|
||||
}
|
||||
|
||||
class _AddressFormTextFieldState extends State<AddressFormTextField> {
|
||||
final Address addressModel = Address();
|
||||
|
||||
String? get _errorText {
|
||||
final text = widget.controller.value.text;
|
||||
return widget.validator(text);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ValueListenableBuilder<TextEditingValue>(
|
||||
valueListenable: widget.controller,
|
||||
builder: (context, value, _) {
|
||||
return Flexible(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(10),
|
||||
child: TextFormField(
|
||||
validator: (value) {
|
||||
print(_zipcodeRegExp.hasMatch(value!));
|
||||
},
|
||||
child: TextField(
|
||||
controller: widget.controller,
|
||||
decoration: InputDecoration(
|
||||
label: Text(label),
|
||||
label: Text(widget.label),
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
errorText: _errorText),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
30
lib/src/models/address.dart
Normal file
30
lib/src/models/address.dart
Normal file
|
@ -0,0 +1,30 @@
|
|||
class Address {
|
||||
Address({
|
||||
this.zipcode,
|
||||
this.street,
|
||||
this.housenumber,
|
||||
this.suffix,
|
||||
this.city,
|
||||
});
|
||||
|
||||
final String? zipcode;
|
||||
final String? street;
|
||||
final int? housenumber;
|
||||
final String? suffix;
|
||||
final String? city;
|
||||
|
||||
Address copyWith({
|
||||
String? zipcode,
|
||||
String? street,
|
||||
int? housenumber,
|
||||
String? suffix,
|
||||
String? city,
|
||||
}) =>
|
||||
Address(
|
||||
zipcode: zipcode ?? this.zipcode,
|
||||
street: street ?? this.street,
|
||||
housenumber: housenumber ?? this.housenumber,
|
||||
suffix: suffix ?? this.suffix,
|
||||
city: city ?? this.city,
|
||||
);
|
||||
}
|
Loading…
Reference in a new issue