diff --git a/packages/wyatt_form_bloc/lib/src/data/data.dart b/packages/wyatt_form_bloc/lib/src/data/data.dart index 743bef59..f86212c5 100644 --- a/packages/wyatt_form_bloc/lib/src/data/data.dart +++ b/packages/wyatt_form_bloc/lib/src/data/data.dart @@ -1,16 +1,16 @@ // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program. If not, see . @@ -32,3 +32,4 @@ export 'input_validators/name.dart'; export 'input_validators/password.dart'; export 'input_validators/phone.dart'; export 'input_validators/text_string.dart'; +export 'repositories/form_repository_impl.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart b/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart index 235ce5c8..9b17b055 100644 --- a/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart +++ b/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart @@ -30,6 +30,7 @@ class WyattFormImpl extends WyattForm { FormInput, dynamic>> _inputs; final FormValidator _validator; + final String _name; late List< FormInput, @@ -37,8 +38,10 @@ class WyattFormImpl extends WyattForm { WyattFormImpl( this._inputs, { + required String name, FormValidator validationStrategy = const EveryInputValidator(), - }) : _validator = validationStrategy { + }) : _name = name, + _validator = validationStrategy { _inputsInitial = _inputs.map((input) => input.clone()).toList(); } @@ -50,6 +53,9 @@ class WyattFormImpl extends WyattForm { @override FormValidator get formValidationStrategy => _validator; + @override + String get name => _name; + @override bool containsKey(String key) => inputs.any((input) => input.key == key); @@ -94,22 +100,24 @@ class WyattFormImpl extends WyattForm { FormStatus validate() => formValidationStrategy.validate(this); @override - WyattForm clone() => WyattFormImpl( - _inputs.map((input) => input.clone()).toList(), - validationStrategy: formValidationStrategy, - ); + WyattForm clone() { + final clone = WyattFormImpl( + _inputs.map((input) => input.clone()).toList(), + name: _name, + validationStrategy: formValidationStrategy, + ).._inputsInitial = _inputsInitial; + return clone; + } @override - WyattForm reset() => WyattFormImpl( - _inputsInitial, - validationStrategy: formValidationStrategy, - ); - - @override - bool? get stringify => true; - - @override - List get props => _inputs; + WyattForm reset() { + final newForm = WyattFormImpl( + _inputsInitial, + name: _name, + validationStrategy: formValidationStrategy, + ).._inputsInitial = _inputsInitial; + return newForm; + } @override void updateMetadata(String key, FormInputMetadata metadata) { @@ -133,4 +141,11 @@ class WyattFormImpl extends WyattForm { @override WyattForm operationWith(FormOperation operation, WyattForm other) => operation.call(this, other); + + @override + List get props => [_inputs, _name, _validator]; + + @override + String toString() => + 'WyattForm(name: $name, validation: ${_validator.runtimeType}, inputs: $inputs)'; } diff --git a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart index 20a5fee4..14a78d9c 100644 --- a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart @@ -44,6 +44,7 @@ class FormDifference extends FormOperation { return WyattFormImpl( inputs, + name: a.name, validationStrategy: a.formValidationStrategy, ); } diff --git a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart index 1a5d75bb..2c1d4cb6 100644 --- a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart @@ -38,6 +38,7 @@ class FormIntersection extends FormOperation { return WyattFormImpl( inputs, + name: a.name, validationStrategy: a.formValidationStrategy, ); } diff --git a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart index 06d0c067..a466750b 100644 --- a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart @@ -42,6 +42,7 @@ class FormUnion extends FormOperation { return WyattFormImpl( inputs, + name: a.name, validationStrategy: a.formValidationStrategy, ); } diff --git a/packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart b/packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart new file mode 100644 index 00000000..0d97327b --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart @@ -0,0 +1,60 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/repositories/form_repository.dart'; + +class FormRepositoryImpl extends FormRepository { + final Map _runtimeForms = {}; + + @override + Map get runtimeForms => _runtimeForms; + + @override + WyattForm accessForm(String formName) { + if (_runtimeForms.containsKey(formName)) { + return _runtimeForms[formName]!; + } else { + throw ClientException( + 'Form $formName is not registered. Just use ' + '`FormRepository.register(yourForm);` before any operation on it.', + ); + } + } + + @override + void registerForm(WyattForm form) { + _runtimeForms[form.name] = form; + } + + @override + void updateForm(WyattForm form) { + if (_runtimeForms.containsKey(form.name)) { + _runtimeForms[form.name] = form; + } else { + throw ClientException( + 'Form ${form.name} is not registered. Just use ' + '`FormRepository.register(yourForm);` before any operation on it.', + ); + } + } + + @override + void unregisterForm(String formName) { + _runtimeForms.remove(formName); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/domain/domain.dart b/packages/wyatt_form_bloc/lib/src/domain/domain.dart index 9eada269..a7eae716 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/domain.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/domain.dart @@ -1,16 +1,16 @@ // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program. If not, see . @@ -21,3 +21,4 @@ export 'form_encoders/form_encoder.dart'; export 'form_operations/form_operation.dart'; export 'form_validators/form_validator.dart'; export 'input_validators/form_input_validator.dart'; +export 'repositories/form_repository.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart index 41eb70aa..b8abfd7e 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart @@ -59,8 +59,9 @@ class FormInput< ); @override - bool? get stringify => true; + List get props => [key, validator, metadata]; @override - List get props => [key, validator, metadata]; + String toString() => + 'FormInput(name: $name, value: ${validator.value}, status: ${validator.status.name}'; } diff --git a/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart b/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart index 718e5be5..1b156c94 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart @@ -28,6 +28,7 @@ import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator abstract class WyattForm extends Equatable { List get inputs; FormValidator get formValidationStrategy; + String get name; bool containsKey(String key); diff --git a/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart b/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart index ab5f34de..eaf8f960 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart @@ -19,5 +19,6 @@ import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; // ignore: one_member_abstracts abstract class FormOperation { const FormOperation(); + // TODO(hpcl): handle operation on `initialInputs` WyattForm call(WyattForm a, WyattForm b); } diff --git a/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart index 16d2e21a..ebb539d3 100644 --- a/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart @@ -18,11 +18,11 @@ import 'package:equatable/equatable.dart'; import 'package:wyatt_form_bloc/src/core/enums/form_input_status.dart'; import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +part 'any_validator.dart'; +part 'equality_validator.dart'; +part 'nullable_validator.dart'; part 'regex_validator.dart'; part 'text_validator.dart'; -part 'nullable_validator.dart'; -part 'equality_validator.dart'; -part 'any_validator.dart'; /// {@template form_input_validator} /// A [FormInputValidator] represents the value of a single form input field. diff --git a/packages/wyatt_form_bloc/lib/src/domain/repositories/form_repository.dart b/packages/wyatt_form_bloc/lib/src/domain/repositories/form_repository.dart new file mode 100644 index 00000000..3b5f1f05 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/domain/repositories/form_repository.dart @@ -0,0 +1,27 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; + +abstract class FormRepository extends BaseRepository { + Map get runtimeForms; + + void registerForm(WyattForm form); + void updateForm(WyattForm form); + WyattForm accessForm(String formName); + void unregisterForm(String formName); +} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart index 50ca2c34..3af6c99b 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart @@ -29,6 +29,8 @@ part 'form_data_state.dart'; abstract class FormDataCubit extends Cubit { FormDataCubit(super.initialState) : super(); + String get formName; + FutureOr dataChanged( String key, FormInputValidator dirtyValue, diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart index b5729d71..2eb50aa7 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart @@ -21,22 +21,31 @@ import 'package:wyatt_form_bloc/src/core/enums/set_operations.dart'; import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; +import 'package:wyatt_form_bloc/src/domain/repositories/form_repository.dart'; import 'package:wyatt_form_bloc/src/presentation/features/form_data/form_data_cubit.dart'; part 'form_data_state_impl.dart'; abstract class FormDataCubitImpl extends FormDataCubit { - FormDataCubitImpl(WyattForm form) : super(FormDataStateImpl(form: form)); + final FormRepository _formRepository; + final String _formName; + + FormDataCubitImpl(this._formRepository, this._formName) + : super(FormDataStateImpl(form: _formRepository.accessForm(_formName))); + + @override + String get formName => _formName; @override FutureOr dataChanged( String key, FormInputValidator dirtyValue, ) { - final form = state.form.clone(); + final form = _formRepository.accessForm(_formName).clone(); try { form.updateValidator(key, dirtyValue); + _formRepository.updateForm(form); } catch (e) { rethrow; } @@ -54,7 +63,9 @@ abstract class FormDataCubitImpl extends FormDataCubit { WyattForm form, { SetOperation operation = SetOperation.replace, }) { - final WyattForm newForm = operation.operation.call(state.form, form); + final WyattForm current = _formRepository.accessForm(_formName).clone(); + final WyattForm newForm = operation.operation.call(current, form); + _formRepository.updateForm(newForm); emit( state.copyWith( @@ -67,6 +78,7 @@ abstract class FormDataCubitImpl extends FormDataCubit { @override FutureOr reset() { final form = state.form.reset(); + _formRepository.updateForm(form); emit( state.copyWith( form: form, diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart index 37cb8e5a..dad01887 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart @@ -35,8 +35,9 @@ class FormDataStateImpl extends FormDataState { ); @override - bool? get stringify => true; + List get props => [status, form, errorMessage]; @override - List get props => [status, form, errorMessage]; + String toString() => + 'FormDataSate(status: ${status.name} ${(errorMessage != null) ? " [$errorMessage]" : ""}, $form'; } diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart index b23e33d2..c6cb9006 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart @@ -35,7 +35,7 @@ class InputBuilder extends StatelessWidget { Widget build(BuildContext context) => BlocBuilder( builder: (context, state) { - final cubit = context.read(); + final cubit = context.watch(); final inputValid = state.form.validatorOf(field).valid; return builder.call(context, cubit, state, field, inputValid); }, diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_text_controller.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_text_controller.dart new file mode 100644 index 00000000..17f5c16e --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_text_controller.dart @@ -0,0 +1,75 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart'; +import 'package:wyatt_form_bloc/src/domain/repositories/form_repository.dart'; +import 'package:wyatt_form_bloc/src/presentation/features/form_data/form_data_cubit.dart'; + +class InputBuilderTextController extends StatelessWidget { + InputBuilderTextController({ + required this.field, + required this.builder, + super.key, + }); + + final String field; + + final Widget Function( + BuildContext context, + Cubit cubit, + FormDataState state, + String field, + bool inputValid, + TextEditingController textEditingController, + FormInputMetadata? metadata, + ) builder; + + final TextEditingController _controller = TextEditingController(); + + @override + Widget build(BuildContext context) { + final formName = context.watch().formName; + final value = + context.read().accessForm(formName).valueOf(field); + _controller + ..text = value ?? '' + ..selection = TextSelection.fromPosition( + TextPosition( + offset: _controller.text.length, + ), + ); + + return BlocBuilder( + builder: (context, state) { + final cubit = context.read(); + final inputValid = state.form.validatorOf(field).valid; + final metadata = state.form.metadataOf(field); + return builder.call( + context, + cubit, + state, + field, + inputValid, + _controller, + metadata, + ); + }, + ); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart b/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart index 31292d02..e0b0377d 100644 --- a/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart @@ -18,4 +18,5 @@ export 'features/form_data/form_data_cubit.dart'; export 'features/form_data_impl/form_data_cubit_impl.dart'; export 'features/widgets/input_builder.dart'; export 'features/widgets/input_builder_metadata.dart'; +export 'features/widgets/input_builder_text_controller.dart'; export 'features/widgets/submit_builder.dart';