Skip to content

Commit

Permalink
chore: cleanup logic using formFieldInstanceRegistry
Browse files Browse the repository at this point in the history
Related to #1142
  • Loading branch information
Skaiir committed Apr 11, 2024
1 parent 6fac076 commit 59d7da6
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 90 deletions.
111 changes: 25 additions & 86 deletions packages/form-js-viewer/src/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,64 +204,38 @@ export class Form {
* @returns {Errors}
*/
validate() {
const formFields = this.get('formFields'),
formFieldRegistry = this.get('formFieldRegistry'),
pathRegistry = this.get('pathRegistry'),
const formFieldRegistry = this.get('formFieldRegistry'),
formFieldInstanceRegistry = this.get('formFieldInstanceRegistry'),
validator = this.get('validator');

const { data } = this._getState();
const errors = {};

const getErrorPath = (field, indexes) => [ field.id, ...Object.values(indexes || {}) ];
const getErrorPath = (id, indexes) => [ id, ...Object.values(indexes || {}) ];

function validateFieldRecursively(errors, field, indexes) {
const { disabled, type, isRepeating } = field;
const { config: fieldConfig } = formFields.get(type);
formFieldInstanceRegistry.getAllKeyed().forEach(({ id, valuePath, indexes }) => {

const field = formFieldRegistry.get(id);

// (1) Skip disabled fields
if (disabled) {
if (field.disabled) {
return;
}

// (2) Validate the field
const valuePath = pathRegistry.getValuePath(field, { indexes });
const valueData = get(data, valuePath);
const fieldErrors = validator.validateField(field, valueData);
const value = get(data, valuePath);
const fieldErrors = validator.validateField(field, value);

if (fieldErrors.length) {
set(errors, getErrorPath(field, indexes), fieldErrors);
}

// (3) Process parents
if (!Array.isArray(field.components)) {
return;
set(errors, getErrorPath(field.id, indexes), fieldErrors);
}

// (4a) Recurse repeatable parents both across the indexes of repetition and the children
if (fieldConfig.repeatable && isRepeating) {

if (!Array.isArray(valueData)) {
return;
}

valueData.forEach((_, index) => {
field.components.forEach((component) => {
validateFieldRecursively(errors, component, { ...indexes, [field.id]: index });
});
});

return;
}

// (4b) Recurse non-repeatable parents only across the children
field.components.forEach((component) => validateFieldRecursively(errors, component, indexes));
}
});

const workingErrors = {};
validateFieldRecursively(workingErrors, formFieldRegistry.getForm());
const filteredErrors = this._applyConditions(workingErrors, data, { getFilterPath: getErrorPath, leafNodeDeletionOnly: true });
this._setState({ errors: filteredErrors });
this._setState({ errors });

return filteredErrors;
// @ts-ignore
return errors;
}

/**
Expand Down Expand Up @@ -442,59 +416,24 @@ export class Form {
*/
_getSubmitData() {
const formFieldRegistry = this.get('formFieldRegistry');
const formFields = this.get('formFields');
const pathRegistry = this.get('pathRegistry');
const formFieldInstanceRegistry = this.get('formFieldInstanceRegistry');
const formData = this._getState().data;

function collectSubmitDataRecursively(submitData, formField, indexes) {
const { disabled, type } = formField;
const { config: fieldConfig } = formFields.get(type);
const submitData = {};

// (1) Process keyed fields
if (!disabled && fieldConfig.keyed) {
const valuePath = pathRegistry.getValuePath(formField, { indexes });
const value = get(formData, valuePath);
set(submitData, valuePath, value);
}

// (2) Process parents
if (!Array.isArray(formField.components)) {
return;
}

// (3a) Recurse repeatable parents both across the indexes of repetition and the children
if (fieldConfig.repeatable && formField.isRepeating) {

const valueData = get(formData, pathRegistry.getValuePath(formField, { indexes }));

if (!Array.isArray(valueData)) {
return;
}

valueData.forEach((_, index) => {
formField.components.forEach((component) => {
collectSubmitDataRecursively(submitData, component, { ...indexes, [formField.id]: index });
});
});
formFieldInstanceRegistry.getAllKeyed().forEach((formFieldInstance) => {
const { id, valuePath } = formFieldInstance;
const { disabled } = formFieldRegistry.get(id);

if (disabled) {
return;
}

// (3b) Recurse non-repeatable parents only across the children
formField.components.forEach((component) => collectSubmitDataRecursively(submitData, component, indexes));
}

const workingSubmitData = {};
collectSubmitDataRecursively(workingSubmitData, formFieldRegistry.getForm(), {});
return this._applyConditions(workingSubmitData, formData);
}
const value = get(formData, valuePath);
set(submitData, valuePath, value);
});

/**
* @internal
*/
_applyConditions(toFilter, data, options = {}) {
const conditionChecker = this.get('conditionChecker');
return conditionChecker.applyConditions(toFilter, data, options);
return submitData;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ export class ConditionChecker {
const workingData = clone(data);

const {
getFilterPath = (field, indexes) => this._pathRegistry.getValuePath(field, { indexes }),
leafNodeDeletionOnly = false
getFilterPath = (field, indexes) => this._pathRegistry.getValuePath(field, { indexes })
} = options;

const _applyConditionsWithinScope = (rootField, scopeContext, startHidden = false) => {
Expand Down Expand Up @@ -60,7 +59,7 @@ export class ConditionChecker {
context.isHidden = startHidden || context.isHidden || (conditional && this._checkHideCondition(conditional, localExpressionContext));

// if a field is repeatable and visible, we need to implement custom recursion on its children
if (isRepeatable && (!context.isHidden || leafNodeDeletionOnly)) {
if (isRepeatable && (!context.isHidden)) {

// prevent the regular recursion behavior of executeRecursivelyOnFields
context.preventRecursion = true;
Expand Down Expand Up @@ -93,7 +92,7 @@ export class ConditionChecker {
}

// if we have a hidden repeatable field, and the data structure allows, we clear it directly at the root and stop recursion
if (context.isHidden && !leafNodeDeletionOnly && isRepeatable) {
if (context.isHidden && isRepeatable) {
context.preventRecursion = true;
this._cleanlyClearDataAtPath(getFilterPath(field, indexes), workingData);
}
Expand Down

0 comments on commit 59d7da6

Please sign in to comment.