Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional fixes for the 5x renderer. #5704

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
492ccdf
Additional fixes for the 5x renderer.
travist Jul 22, 2024
40b3606
Merge branch 'master' of github.com:formio/formio.js into additional-…
travist Jul 22, 2024
fce1a86
Merge branch 'master' of github.com:formio/formio.js into additional-…
travist Jul 23, 2024
9b15cd0
Merge branch 'master' of github.com:formio/formio.js into additional-…
travist Jul 29, 2024
81b1b13
Merge branch 'master' of github.com:formio/formio.js into additional-…
travist Aug 13, 2024
8f49547
Fixing issues where the wrong urls are used for CDN on remote environ…
travist Aug 14, 2024
1818752
Merge branch 'master' of github.com:formio/formio.js into fixing-cdn-url
travist Sep 6, 2024
37e2422
Adding jsdocs.
travist Sep 6, 2024
50db01f
Merge branch 'fixing-cdn-url' into additional-5x-changes
travist Sep 6, 2024
76caa34
Merge branch 'master' of github.com:formio/formio.js into additional-…
travist Oct 3, 2024
5e1bc9f
Merge branch 'master' of github.com:formio/formio.js into additional-…
travist Oct 20, 2024
36da3cb
Merge branch 'master' of github.com:formio/formio.js into additional-…
travist Nov 4, 2024
fe26372
Merge branch 'master' of github.com:formio/formio.js into additional-…
travist Nov 5, 2024
9a6dc0c
Merge branch 'master' of github.com:formio/formio.js into additional-…
travist Nov 8, 2024
df110d2
Changing the paths to use the component paths.
travist Nov 12, 2024
53e9daf
Changing the path strategy to not require stateful objects on compone…
travist Nov 15, 2024
7fb789c
Merge branch 'master' of github.com:formio/formio.js into additional-…
travist Nov 18, 2024
6ff4457
Adding other scope options to the processors.
travist Nov 18, 2024
0c8ba4b
Fixing the eachComponent reference in webform to use the correct one.
travist Nov 18, 2024
305d7f0
Fixing edit grid row validations.
travist Nov 18, 2024
259ad94
Fixing the conditions to use the correct path.
travist Nov 19, 2024
61a16bb
Merge branch 'master' of github.com:formio/formio.js into additional-…
travist Nov 19, 2024
722333b
Changing timing to trigger validations.
travist Nov 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"dependencies": {
"@formio/bootstrap": "3.0.0-dev.98.17ba6ea",
"@formio/choices.js": "^10.2.1",
"@formio/core": "2.1.0-dev.191.8c609ab",
"@formio/core": "2.1.0-dev.189.e38e07a",
"@formio/text-mask-addons": "^3.8.0-formio.3",
"@formio/vanilla-text-mask": "^5.1.1-formio.1",
"abortcontroller-polyfill": "^1.7.5",
Expand Down
51 changes: 25 additions & 26 deletions src/Webform.js
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,7 @@ export default class Webform extends NestedDataComponent {
try {
// Do not set the form again if it has been already set
if (isFormAlreadySet && JSON.stringify(this._form) === JSON.stringify(form)) {
this.formReadyResolve();
return Promise.resolve();
}

Expand All @@ -671,11 +672,13 @@ export default class Webform extends NestedDataComponent {
}

if (this.parent?.component?.modalEdit) {
this.formReadyResolve();
return Promise.resolve();
}
} catch (err) {
console.warn(err);
// If provided form is not a valid JSON object, do not set it too
this.formReadyReject(err);
return Promise.resolve();
}

Expand Down Expand Up @@ -959,6 +962,9 @@ export default class Webform extends NestedDataComponent {
}

getValue() {
if (!this._submission) {
this._submission = {};
}
if (!this._submission.data) {
this._submission.data = {};
}
Expand Down Expand Up @@ -1271,32 +1277,24 @@ export default class Webform extends NestedDataComponent {
}

// Mark any components as invalid if in a custom message.
const componentErrors = {};
errors.forEach((err) => {
const { components = [] } = err;
if (err.component) {
components.push(err.component);
const path = err.path || err.context?.path || err.component?.key;
if (!componentErrors[path]) {
componentErrors[path] = [];
}
componentErrors[path].push(err);
});

if (err.path) {
components.push(err.path);
// Iterate through all of our component errors and apply them to the components.
for (let path in componentErrors) {
const component = this.getComponent(path);
const errors = componentErrors[path];
if (component) {
component.serverErrors = errors.filter((err) => err.fromServer);
component.setCustomValidity(errors, true)
}

components.forEach((path) => {
const originalPath = getStringFromComponentPath(path);
const component = this.getComponent(path, _.identity, originalPath);

if (err.fromServer) {
if (component.serverErrors) {
component.serverErrors.push(err);
} else {
component.serverErrors = [err];
}
}
const components = _.compact(Array.isArray(component) ? component : [component]);

components.forEach((component) => component.setCustomValidity(err.message, true));
});
});
}

const displayedErrors = [];
if (errors.length) {
Expand Down Expand Up @@ -1521,7 +1519,7 @@ export default class Webform extends NestedDataComponent {
});
}

submitForm(options = {}) {
submitForm(options = {}, local = false) {
this.clearServerErrors();

return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -1556,6 +1554,7 @@ export default class Webform extends NestedDataComponent {
return reject("Invalid Submission");
}
const errors = this.validate(submission.data, {
local,
dirty: true,
silentCheck: false,
process: "submit",
Expand All @@ -1575,11 +1574,11 @@ export default class Webform extends NestedDataComponent {

this.everyComponent((comp) => {
if (submission._vnote && comp.type === "form" && comp.component.reference) {
_.get(submission.data, comp.path, {})._vnote = submission._vnote;
_.get(submission.data, local ? comp.paths?.localDataPath : comp.path, {})._vnote = submission._vnote;
}
const { persistent } = comp.component;
if (persistent === "client-only") {
_.unset(submission.data, comp.path);
_.unset(submission.data, local ? comp.paths?.localDataPath : comp.path);
}
});

Expand Down Expand Up @@ -1777,7 +1776,7 @@ export default class Webform extends NestedDataComponent {
return;
}
const captchaComponent = [];
eachComponent(this.components, (component) => {
this.eachComponent((component) => {
if (/^(re)?captcha$/.test(component.type) && component.component.eventType === 'formLoad') {
captchaComponent.push(component);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Wizard.js
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ export default class Wizard extends Webform {

attachHeader() {
const isAllowPrevious = this.isAllowPrevious();
this.attachTooltips(this.refs[`${this.wizardKey}-tooltip`], this.currentPanel.tooltip);
this.attachTooltips(this.refs[`${this.wizardKey}-tooltip`], this.currentPanel?.tooltip);

if (this.isBreadcrumbClickable() || isAllowPrevious) {
this.refs[`${this.wizardKey}-link`]?.forEach((link, index) => {
Expand Down Expand Up @@ -1080,7 +1080,7 @@ export default class Wizard extends Webform {
errors = [...errors, ...subWizard.errors]
}
})
};
}
return super.showErrors(errors, triggerEvent)
}

Expand Down
34 changes: 1 addition & 33 deletions src/components/Components.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Component from './_classes/component/Component';
import EditFormUtils from './_classes/component/editForm/utils';
import BaseEditForm from './_classes/component/Component.form';
import { getComponentKey, getModelType } from '../utils/utils';
import _ from 'lodash';
export default class Components {
static _editFormUtils = EditFormUtils;
Expand Down Expand Up @@ -57,35 +56,6 @@ export default class Components {
Components.components[name] = comp;
}

/**
* Return a path of component's value.
* @param {Component} component - The component instance.
* @returns {string} - The component's value path.
*/
static getComponentPath(component) {
let path = '';
const componentKey = getComponentKey(component.component);
if (componentKey) {
let thisPath = component.options?.parent || component;
while (thisPath && !thisPath.allowData && thisPath.parent) {
thisPath = thisPath.parent;
}
// TODO: any component that is nested in e.g. a Data Grid or an Edit Grid is going to receive a row prop; the problem
// is that options.row is passed to each further nested component, which results in erroneous paths like
// `editGrid[0].container[0].textField` rather than `editGrid[0].container.textField`. This should be adapted for other
// components with a tree-like data model
const rowIndex = component.row;
const rowIndexPath = rowIndex && !['container'].includes(thisPath.component.type) ? `[${Number.parseInt(rowIndex)}]` : '';
path = `${thisPath.path}${rowIndexPath}.`;
if (rowIndexPath && getModelType(thisPath) === 'nestedDataArray') {
path = `${path}data.`;
}
path += componentKey;
return _.trim(path, '.');
}
return path;
}

static create(component, options, data) {
let comp = null;
if (component.type && Components.components.hasOwnProperty(component.type)) {
Expand All @@ -110,9 +80,7 @@ export default class Components {
else {
comp = new Component(component, options, data);
}
const path = Components.getComponentPath(comp);
if (path) {
comp.path = path;
if (comp.path) {
comp.componentsMap[comp.path] = comp;
}
return comp;
Expand Down
69 changes: 54 additions & 15 deletions src/components/_classes/component/Component.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { Formio } from '../../../Formio';
import * as FormioUtils from '../../../utils/utils';
import {
fastCloneDeep, boolValue, getComponentPath, isInsideScopingComponent, currentTimezone, getScriptPlugin
fastCloneDeep, boolValue, isInsideScopingComponent, currentTimezone, getScriptPlugin, getContextualRowData
} from '../../../utils/utils';
import Element from '../../../Element';
import ComponentModal from '../componentModal/ComponentModal';
Expand Down Expand Up @@ -256,6 +256,11 @@
*/
this._hasCondition = null;

/**
* The row index for this component.
*/
this._rowIndex = undefined;

/**
* References to dom elements
*/
Expand All @@ -270,12 +275,6 @@
_.merge(component, this.options.components[component.type]);
}

/**
* The data path to this specific component instance.
* @type {string}
*/
this.path = component?.key || '';

/**
* An array of all the children components errors.
*/
Expand Down Expand Up @@ -360,6 +359,14 @@
*/
this.parent = this.options.parent;

/**
* The component paths for this component.
* @type {import('@formio/core').ComponentPaths} - The component paths.
*/
this.paths = FormioUtils.getComponentPaths(this.component, this.parent?.component, {
...this.parent?.paths,
dataIndex: this.options.rowIndex === undefined ? this.parent?.paths?.dataIndex : this.options.rowIndex
});
this.options.name = this.options.name || 'data';

this._path = '';
Expand Down Expand Up @@ -479,12 +486,7 @@
/* eslint-enable max-statements */

get componentsMap() {
if (this.localRoot?.childComponentsMap) {
return this.localRoot.childComponentsMap;
}
const localMap = {};
localMap[this.path] = this;
return localMap;
return this.root.childComponentsMap;
}

get data() {
Expand Down Expand Up @@ -541,6 +543,27 @@
}
}

/**
* Get Row Index.
* @returns {number} - The row index.
*/
get rowIndex() {
return this._rowIndex;
}

/**
* Set Row Index to row and update each component.
* @param {number} value - The row index.
* @returns {void}
*/
set rowIndex(value) {
this.paths = FormioUtils.getComponentPaths(this.component, this.parent?.component, {
...(this.parent?.paths || {}),
...{ dataIndex: value }
});
this._rowIndex = value;
}

afterComponentAssign() {
//implement in extended classes
}
Expand Down Expand Up @@ -623,6 +646,14 @@
return _.get(this.component, 'key', '');
}

get path() {
return this.paths.dataPath;
}

set path(path) {
throw new Error('Should not be setting the path of a component.');
}

set parentVisible(value) {
this._parentVisible = value;
}
Expand Down Expand Up @@ -1457,7 +1488,7 @@
this.refresh(this.data, changed, flags);
}
else if (
(changePath && getComponentPath(changed.instance) === refreshData) && changed && changed.instance &&
(changePath && (changed.instance?.paths?.localPath === refreshData)) && changed && changed.instance &&
// Make sure the changed component is not in a different "context". Solves issues where refreshOn being set
// in fields inside EditGrids could alter their state from other rows (which is bad).
this.inContext(changed.instance)
Expand Down Expand Up @@ -2969,7 +3000,7 @@

/**
* Returns if the value (e.g. array) should be divided between several inputs
* @returns {boolean}

Check warning on line 3003 in src/components/_classes/component/Component.js

View workflow job for this annotation

GitHub Actions / setup

Missing JSDoc @returns description
*/
isSingleInputValue() {
return false;
Expand Down Expand Up @@ -3311,6 +3342,9 @@
* @returns {string} - The message to show when the component is invalid.
*/
invalidMessage(data, dirty, ignoreCondition, row) {
if (!row) {
row = getContextualRowData(this.component, data, this.paths);
}
if (!ignoreCondition && !this.checkCondition(row, data)) {
return '';
}
Expand All @@ -3331,6 +3365,8 @@
data,
row,
path: this.path || this.component.key,
parent: this.parent?.component,
paths: this.paths,
scope: validationScope,
instance: this,
processors: [
Expand Down Expand Up @@ -3388,7 +3424,7 @@
if (flags.silentCheck) {
return [];
}
let isDirty = this.dirty || flags.dirty;
let isDirty = (flags.dirty === false) ? false : (this.dirty || flags.dirty);
if (this.options.alwaysDirty) {
isDirty = true;
}
Expand All @@ -3414,7 +3450,10 @@
component: this.component,
data,
row,
local: !!flags.local,
value: this.validationValue,
parent: this.parent?.component,
paths: this.paths,
path: this.path || this.component.key,
instance: this,
form: this.root ? this.root._form : {},
Expand Down
Loading
Loading