Skip to content

Commit

Permalink
Made it so that visibleIf is respected. Does not yet handle multiple …
Browse files Browse the repository at this point in the history
…conditions chained with AND or OR - DC
  • Loading branch information
ChopinDavid committed Jul 31, 2023
1 parent ba2bcc4 commit a079b82
Show file tree
Hide file tree
Showing 7 changed files with 761 additions and 69 deletions.
145 changes: 145 additions & 0 deletions lib/data/condition/visibility_helper.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import 'package:flutter_survey_js/survey.dart';

class VisibilityHelper {
bool isElementVisible(
{required Question element,
required Map<String, dynamic> surveyResponse}) {
final VisibilityHelper visibilityHelper = VisibilityHelper();
bool isVisible = true;
String? visibleIf = element.visibleIf?.replaceAll(' ', '');
if (visibleIf == null) {
return true;
}
void findMatch(Map<String, dynamic> surveyResponse) {
if (!_curlyBraceRegExp.hasMatch(visibleIf!)) {
return;
}
final match = _curlyBraceRegExp.firstMatch(visibleIf!);
final matchedString =
match?.group(0)!.replaceAll('{', '').replaceAll('}', '');
String comparisonOperator =
visibilityHelper.determineComparisonOperatorString(
matchedElementName: match!, visibleIf: visibleIf!);

dynamic rightOperand = visibilityHelper.determineRightOperand(
visibleIf: visibleIf!,
matchedElementName: match,
comparisonOperatorLength: comparisonOperator.length);

visibleIf = visibleIf!.replaceFirst(_curlyBraceRegExp, '');

if (rightOperand is num) {
if (surveyResponse[matchedString] == null) {
isVisible = false;
return;
}
switch (comparisonOperator) {
case '=':
if (surveyResponse[matchedString] != rightOperand) {
isVisible = false;
return;
}
break;
case '<':
if (surveyResponse[matchedString] >= rightOperand) {
isVisible = false;
return;
}
break;
case '<=':
if (surveyResponse[matchedString] > rightOperand) {
isVisible = false;
return;
}
break;
case '>':
if (surveyResponse[matchedString] <= rightOperand) {
isVisible = false;
return;
}
break;
case '>=':
if (surveyResponse[matchedString] < rightOperand) {
isVisible = false;
return;
}
break;
}
} else {
rightOperand = rightOperand.substring(1, rightOperand.length - 1);
if (surveyResponse[matchedString] != '$rightOperand') {
isVisible = false;
return;
}
}
findMatch(surveyResponse);
}

findMatch(surveyResponse);
return isVisible;
}

final RegExp _curlyBraceRegExp = RegExp(r'{(.*?)}');
final List<String> _comparisonOperatorSymbols = ['=', '<', '>'];

String determineComparisonOperatorString(
{required String visibleIf, required RegExpMatch matchedElementName}) {
String comparisonOperator = '';
void evaluateChar() {
final String charToCheck = visibleIf.substring(
matchedElementName.end + comparisonOperator.length,
matchedElementName.end + comparisonOperator.length + 1);
if (_comparisonOperatorSymbols.contains(charToCheck)) {
comparisonOperator += charToCheck;
evaluateChar();
}
}

evaluateChar();
return comparisonOperator;
}

dynamic determineRightOperand(
{required String visibleIf,
required RegExpMatch matchedElementName,
required int comparisonOperatorLength}) {
bool rightOperandIsNum = false;
String rightOperand = '';

void evaluateChar() {
if ((matchedElementName.end +
comparisonOperatorLength +
rightOperand.length +
1) >
visibleIf.length) {
return;
}
final String charToCheck = visibleIf.substring(
matchedElementName.end +
comparisonOperatorLength +
rightOperand.length,
matchedElementName.end +
comparisonOperatorLength +
rightOperand.length +
1);
if (rightOperand.isEmpty) {
if (charToCheck != '\'') {
rightOperandIsNum = true;
}
} else {
if ((rightOperandIsNum && int.tryParse(charToCheck) != null)) {
return;
}
if (charToCheck == '\'') {
rightOperand += charToCheck;
return;
}
}
rightOperand += charToCheck;
evaluateChar();
}

evaluateChar();
return rightOperandIsNum ? int.parse(rightOperand) : rightOperand;
}
}
61 changes: 34 additions & 27 deletions lib/ui/elements/matrix_dropdown.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,34 +56,41 @@ class MatrixDropdownElement extends StatelessWidget {
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: Text(row.castToItemvalue().text ?? "")),
...(matrix.columns?.toList() ?? []).map((column) {
final q = matrixDropdownColumnToQuestion(matrix, column);
final v = questionToValidators(q);
...(matrix.columns?.toList() ?? [])
.map((column) {
final q = matrixDropdownColumnToQuestion(matrix, column);
final v = questionToValidators(q);
final element = SurveyConfiguration.of(context)!
.factory
.resolve(context, q,
configuration:
const ElementConfiguration(hasTitle: false));

return TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: ReactiveNestedForm(
formControlName:
row.castToItemvalue().value!.toString(),
child: Builder(
builder: (context) {
final fg = ReactiveForm.of(context) as FormGroup;
final c = fg.control(column.name!);
//TODO runner
// //concat validators
// final newV = HashSet<ValidatorFunction>.of(
// [...c.validators, ...v]).toList();
c.setValidators(v);
return SurveyConfiguration.of(context)!
.factory
.resolve(
context, q,
configuration: const ElementConfiguration(
hasTitle: false));
},
),
));
}).toList()
return element == null
? null
: TableCell(
verticalAlignment:
TableCellVerticalAlignment.middle,
child: ReactiveNestedForm(
formControlName:
row.castToItemvalue().value!.toString(),
child: Builder(
builder: (context) {
final fg =
ReactiveForm.of(context) as FormGroup;
final c = fg.control(column.name!);
//TODO runner
// //concat validators
// final newV = HashSet<ValidatorFunction>.of(
// [...c.validators, ...v]).toList();
c.setValidators(v);
return element;
},
),
));
})
.toList()
.removeWhere((element) => element == null) as List<Widget>
]));
});

Expand Down
65 changes: 36 additions & 29 deletions lib/ui/elements/matrix_dynamic.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import 'package:flutter/material.dart';
import 'package:flutter_survey_js/generated/l10n.dart';
import 'package:flutter_survey_js/ui/custom_scroll_behavior.dart';
import 'package:flutter_survey_js/ui/reactive/reactive_wrap_form_array.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:flutter_survey_js/ui/form_control.dart';
import 'package:flutter_survey_js/ui/reactive/reactive_nested_form.dart';
import 'package:flutter_survey_js/ui/reactive/reactive_wrap_form_array.dart';
import 'package:flutter_survey_js/ui/survey_configuration.dart';
import 'package:flutter_survey_js/ui/validators.dart';
import 'package:flutter_survey_js_model/flutter_survey_js_model.dart' as s;
import 'package:reactive_forms/reactive_forms.dart';

import 'matrix_dropdown_base.dart';
Expand Down Expand Up @@ -89,33 +89,40 @@ class MatrixDynamicElement extends StatelessWidget {
)
: null,
children: [
...(matrix.columns?.toList() ?? []).map((column) {
final q = matrixDropdownColumnToQuestion(matrix, column);
final v = questionToValidators(q);
...(matrix.columns?.toList() ?? [])
.map((column) {
final q = matrixDropdownColumnToQuestion(matrix, column);
final v = questionToValidators(q);
final element = SurveyConfiguration.of(context)!
.factory
.resolve(context, q,
configuration:
const ElementConfiguration(hasTitle: false));

return TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: ReactiveNestedForm(
formGroup: c,
child: Builder(
builder: (context) {
final fg = ReactiveForm.of(context) as FormGroup;
final c = fg.control(column.name!);
//concat validators
// final newV = HashSet<ValidatorFunction>.of(
// [...c.validators, ...v]).toList();
//TODO runner
c.setValidators(v);
return SurveyConfiguration.of(context)!
.factory
.resolve(
context, q,
configuration: const ElementConfiguration(
hasTitle: false));
},
),
));
}).toList(),
return element == null
? null
: TableCell(
verticalAlignment:
TableCellVerticalAlignment.middle,
child: ReactiveNestedForm(
formGroup: c,
child: Builder(
builder: (context) {
final fg =
ReactiveForm.of(context) as FormGroup;
final c = fg.control(column.name!);
//concat validators
// final newV = HashSet<ValidatorFunction>.of(
// [...c.validators, ...v]).toList();
//TODO runner
c.setValidators(v);
return element;
},
),
));
})
.toList()
.removeWhere((element) => element == null) as List<Widget>,
TableCell(
child: SizedBox(
child: Padding(
Expand Down
3 changes: 1 addition & 2 deletions lib/ui/survey_configuration.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_survey_js/ui/elements/question_title.dart';
import 'package:flutter_survey_js/ui/survey_element_factory.dart';

import 'package:flutter_survey_js_model/flutter_survey_js_model.dart' as s;
import 'package:reactive_forms/reactive_forms.dart';

typedef SurveyElementBuilder = Widget Function(
typedef SurveyElementBuilder = Widget? Function(
BuildContext context, s.Elementbase element,
{ElementConfiguration? configuration});
typedef SurveyFormControlBuilder = AbstractControl Function(
Expand Down
12 changes: 10 additions & 2 deletions lib/ui/survey_element_factory.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import 'package:flutter/material.dart';
import 'package:flutter_survey_js/data/condition/visibility_helper.dart';
import 'package:flutter_survey_js/ui/elements/boolean.dart';
import 'package:flutter_survey_js/ui/elements/comment.dart';
import 'package:flutter_survey_js/ui/elements/matrix_dropdown.dart';
import 'package:flutter_survey_js/ui/elements/panel.dart';
import 'package:flutter_survey_js/ui/reactive/always_update_form_array.dart';
import 'package:flutter_survey_js/ui/reactive/reactive.dart';
import 'package:flutter_survey_js/ui/reactive/reactive_signature_string.dart';
import 'package:flutter_survey_js/ui/survey_configuration.dart';
import 'package:flutter_survey_js/ui/survey_widget.dart';
import 'package:flutter_survey_js/ui/validators.dart';
import 'package:flutter_survey_js_model/flutter_survey_js_model.dart' as s;
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
Expand Down Expand Up @@ -183,8 +184,15 @@ class SurveyElementFactory {
}

// resolve resolve widet from element
Widget resolve(BuildContext context, s.Elementbase element,
Widget? resolve(BuildContext context, s.Elementbase element,
{ElementConfiguration? configuration}) {
if (element is s.Question) {
if (!VisibilityHelper().isElementVisible(
element: element,
surveyResponse: SurveyProvider.of(context).formGroup.value)) {
return null;
}
}
var res = _map[element.type];
if (res == null) {
//unsupported element
Expand Down
Loading

0 comments on commit a079b82

Please sign in to comment.