Skip to content

Commit

Permalink
fix factory
Browse files Browse the repository at this point in the history
  • Loading branch information
goxiaoy committed May 17, 2023
1 parent e2cb5f1 commit 335f91d
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 76 deletions.
1 change: 0 additions & 1 deletion example/lib/components/custom_layout.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_survey_js/survey.dart' as s;
import 'package:flutter_survey_js/ui/survey_configuration.dart';
import 'package:flutter_survey_js/ui/survey_element_factory.dart';
import 'package:flutter_survey_js/ui/survey_widget.dart';
import 'package:json_editor/json_editor.dart';
import 'package:logging/logging.dart';
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/elements/matrix_dynamic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class MatrixDynamicElement extends StatelessWidget {
Widget build(BuildContext context) {
createNew() {
//create new formGroup
return elementsToFormGroup((matrix.columns?.toList() ?? [])
return elementsToFormGroup(context,(matrix.columns?.toList() ?? [])
.map((column) => matrixDropdownColumnToQuestion(matrix, column))
.toList());
}
Expand Down
9 changes: 6 additions & 3 deletions lib/ui/elements/multiple_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ Widget multipleTextBuilder(context, element,
shrinkWrap: true,
itemCount: texts.length,
itemBuilder: (BuildContext context, int index) {
final res = SurveyElementFactory().resolve(context, texts[index]);
final res = SurveyConfiguration.of(context)!
.factory
.resolve(context, texts[index]);
return index == 0
? Padding(
padding: EdgeInsets.only(top: 8.0),
Expand All @@ -34,11 +36,12 @@ Widget multipleTextBuilder(context, element,
).wrapQuestionTitle(context, element, configuration: configuration));
}

AbstractControl multipleTextControlBuilder(s.Elementbase element,
AbstractControl multipleTextControlBuilder(
BuildContext context, s.Elementbase element,
{validators = const []}) {
final e = element as s.Multipletext;
final texts = (e.items?.toList() ?? []).map(toText).toList();
final res = elementsToFormGroup(texts, validators: validators);
final res = elementsToFormGroup(context, texts, validators: validators);
return res;
}

Expand Down
7 changes: 5 additions & 2 deletions lib/ui/elements/panel_dynamic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class PanelDynamicElement extends StatelessWidget {
createNew() {
//create new formGroup
return elementsToFormGroup(
context,
(element.templateElements?.map((p0) => p0.realElement).toList() ?? [])
.toList());
}
Expand All @@ -48,8 +49,10 @@ class PanelDynamicElement extends StatelessWidget {
shrinkWrap: true,
itemCount: element.templateElements?.length ?? 0,
itemBuilder: (BuildContext context, int index) {
final res = SurveyElementFactory().resolve(context,
element.templateElements![index].realElement);
final res = SurveyConfiguration.of(context)!
.factory
.resolve(context,
element.templateElements![index].realElement);
return res;
},
separatorBuilder: (BuildContext context, int index) {
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/elements/text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Widget textBuilder(context, element, {ElementConfiguration? configuration}) {
configuration: configuration);
}

AbstractControl textControlBuilder(s.Elementbase element,
AbstractControl textControlBuilder(BuildContext context, s.Elementbase element,
{validators = const <ValidatorFunction>[]}) {
final e = element as s.Text;
if (e.inputType == s.TextInputType.date ||
Expand Down
109 changes: 55 additions & 54 deletions lib/ui/form_control.dart
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
import 'package:flutter/material.dart';
import 'package:flutter_survey_js/ui/survey_element_factory.dart';
import 'package:flutter_survey_js/survey.dart';
import 'package:flutter_survey_js_model/flutter_survey_js_model.dart' as s;
import 'package:reactive_forms/reactive_forms.dart';

import 'elements/matrix_dropdown_base.dart';
import 'validators.dart';

// elementsToFormGroup mapping question json elements to FormGroup
FormGroup elementsToFormGroup(List<s.Elementbase> elements,
FormGroup elementsToFormGroup(
BuildContext context, List<s.Elementbase> elements,
{Map<s.Elementbase, Object>? controlsMap,
List<ValidatorFunction> validators = const [],
List<AsyncValidatorFunction> asyncValidators = const []}) {
final Map<String, Object> controls = <String, Object>{};
for (var element in elements) {
//the behavior of panel seems different from previous version --2023/04/26 Goxiaoy
if (element.name != null && element is! s.Panel) {
final obj = element.toFormObject(controlsMap: controlsMap);
final obj = toFormObject(context, element, controlsMap: controlsMap);
controls[element.name!] = obj;
if (controlsMap != null) {
controlsMap[element] = obj;
}
} else {
//patch parent
final obj = element.toFormObject(controlsMap: controlsMap);
final obj = toFormObject(context, element, controlsMap: controlsMap);
if (obj is FormGroup) {
controls.addAll(obj.controls);
}
Expand All @@ -31,59 +32,59 @@ FormGroup elementsToFormGroup(List<s.Elementbase> elements,
return fb.group(controls, validators, asyncValidators);
}

extension ElementExtension on s.Elementbase {
// toFormObject convert question json element to FromControl
Object toFormObject({Map<s.Elementbase, Object>? controlsMap}) {
formFunc() {
if (this is s.Panel) {
final p = this as s.Panel;
return elementsToFormGroup(
p.elementsOrQuestions?.map((p) => p.realElement).toList() ?? [],
validators: p.isRequired == true ? [Validators.required] : [],
controlsMap: controlsMap);
}
if (this is s.Paneldynamic) {
return fb
.array((this as s.Paneldynamic).defaultValue.tryCastToListObj());
}
if (this is s.Matrixdynamic) {
return fb
.array((this as s.Matrixdynamic).defaultValue.tryCastToListObj());
}
if (this is s.Matrix) {
final m = this as s.Matrix;
return fb.group(Map.fromEntries(
(m.rows?.map((p) => p.castToItemvalue()) ?? []).map((e) => MapEntry(
e.value.toString(), FormControl<Object>(value: null)))));
}
if (this is s.Matrixdropdown) {
final m = this as s.Matrixdropdown;
return fb.group(Map.fromEntries(
(m.rows?.map((p) => p.castToItemvalue()) ?? []).map((e) => MapEntry(
e.value.toString(),
elementsToFormGroup((m.columns?.toList() ?? [])
.map((column) => matrixDropdownColumnToQuestion(m, column))
.toList())))));
}
final validators = <ValidatorFunction>[];
if (this is s.Question) {
validators.addAll(questionToValidators(this as s.Question));
}
final c = SurveyElementFactory().resolveFormControl(this);

final res = c?.call(this, validators: validators) ??
FormControl<Object>(
validators: validators,
);
return res;
// toFormObject convert question json element to FromControl
Object toFormObject(BuildContext context, s.Elementbase element,
{Map<s.Elementbase, Object>? controlsMap}) {
formFunc() {
if (element is s.Panel) {
return elementsToFormGroup(context,
element.elementsOrQuestions?.map((p) => p.realElement).toList() ?? [],
validators: element.isRequired == true ? [Validators.required] : [],
controlsMap: controlsMap);
}

final obj = formFunc();
if (controlsMap != null) {
controlsMap[this] = obj;
if (element is s.Paneldynamic) {
return fb.array((element).defaultValue.tryCastToListObj());
}
return obj;
if (element is s.Matrixdynamic) {
return fb.array(element.defaultValue.tryCastToListObj());
}
if (element is s.Matrix) {
return fb.group(Map.fromEntries(
(element.rows?.map((p) => p.castToItemvalue()) ?? []).map((e) =>
MapEntry(e.value.toString(), FormControl<Object>(value: null)))));
}
if (element is s.Matrixdropdown) {
return fb.group(Map.fromEntries(
(element.rows?.map((p) => p.castToItemvalue()) ?? []).map((e) =>
MapEntry(
e.value.toString(),
elementsToFormGroup(
context,
(element.columns?.toList() ?? [])
.map((column) =>
matrixDropdownColumnToQuestion(element, column))
.toList())))));
}
final validators = <ValidatorFunction>[];
if (element is s.Question) {
validators.addAll(questionToValidators(element));
}
final c =
((SurveyConfiguration.of(context)?.factory) ?? SurveyElementFactory())
.resolveFormControl(element);

final res = c?.call(context, element, validators: validators) ??
FormControl<Object>(
validators: validators,
);
return res;
}

final obj = formFunc();
if (controlsMap != null) {
controlsMap[element] = obj;
}
return obj;
}

String? getErrorTextFromFormControl<T>(
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/survey_configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ typedef SurveyElementBuilder = Widget Function(
BuildContext context, s.Elementbase element,
{ElementConfiguration? configuration});
typedef SurveyFormControlBuilder = AbstractControl
Function(s.Elementbase element, {List<ValidatorFunction> validators});
Function(BuildContext context,s.Elementbase element, {List<ValidatorFunction> validators});

typedef SurveyTitleBuilder = Widget Function(
BuildContext context, s.Elementbase element, Widget child);
Expand Down
22 changes: 12 additions & 10 deletions lib/ui/survey_element_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,21 @@ class SurveyElementFactory {
register<s.Matrixdropdown>(matrixDropdownBuilder);
register<s.Matrixdynamic>(matrixDynamicBuilder);
register<s.Checkbox>(checkBoxBuilder,
control: (element, {validators = const []}) =>
control: (context, element, {validators = const []}) =>
fb.array([], validators));
register<s.Ranking>(rankingBuilder,
control: (element, {validators = const []}) =>
control: (context, element, {validators = const []}) =>
FormControl<List<dynamic>>(validators: validators));
register<s.Radiogroup>(radioGroupBuilder);
register<s.Boolean>(booleanBuilder,
control: (element, {validators = const []}) =>
control: (context, element, {validators = const []}) =>
FormControl<bool>(validators: validators));

register<s.Rating>(ratingBuilder,
control: (element, {validators = const []}) => FormControl<int>(
validators: validators,
value: (element as s.Rating).defaultValue.tryCastToInt()));
control: (context, element, {validators = const []}) =>
FormControl<int>(
validators: validators,
value: (element as s.Rating).defaultValue.tryCastToInt()));

register<s.Comment>(commentBuilder);

Expand All @@ -71,7 +72,7 @@ class SurveyElementFactory {
);
}).wrapQuestionTitle(context, element, configuration: configuration);
},
control: (_, {validators = const []}) =>
control: (context, _, {validators = const []}) =>
FormControl<String>(validators: validators));
register<s.Image>((context, element,
{ElementConfiguration? configuration}) {
Expand All @@ -81,9 +82,10 @@ class SurveyElementFactory {
// register<s.ImagePicker>(imagePickerBuilder);

register<s.Dropdown>(dropdownBuilder,
control: (element, {validators = const []}) => FormControl<Object>(
validators: validators,
value: (element as s.Dropdown).defaultValue?.toString()));
control: (context, element, {validators = const []}) =>
FormControl<Object>(
validators: validators,
value: (element as s.Dropdown).defaultValue?.toString()));
register<s.Paneldynamic>(panelDynamicBuilder);
register<s.Panel>(panelBuilder);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/survey_page_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class SurveyPageWidgetState extends State<SurveyPageWidget> {
itemBuilder: (context, index) {
if (index < widget.page.elementsOrQuestions!.length &&
index >= 0) {
return SurveyElementFactory().resolve(
return SurveyConfiguration.of(context)!.factory.resolve(
context,
widget
.page.elementsOrQuestions![index].realElement);
Expand Down
4 changes: 2 additions & 2 deletions lib/ui/survey_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_survey_js/survey.dart';
import 'package:flutter_survey_js/ui/survey_configuration.dart';
import 'package:flutter_survey_js_model/flutter_survey_js_model.dart' as s;
import 'package:logging/logging.dart';
import 'package:reactive_forms/reactive_forms.dart';
Expand Down Expand Up @@ -41,6 +40,7 @@ class SurveyWidget extends StatefulWidget {
State<StatefulWidget> createState() => SurveyWidgetState();
}


class SurveyWidgetState extends State<SurveyWidget> {
final Logger logger = Logger('SurveyWidgetState');
late FormGroup formGroup;
Expand Down Expand Up @@ -121,7 +121,7 @@ class SurveyWidgetState extends State<SurveyWidget> {
_controlsMap = {};
_currentPage = 0;

formGroup = elementsToFormGroup(widget.survey.getElements(),
formGroup = elementsToFormGroup(context, widget.survey.getElements(),
controlsMap: _controlsMap);

if (widget.answer != null) {
Expand Down

0 comments on commit 335f91d

Please sign in to comment.