diff --git a/packages/form-js-viewer/assets/form-js-base.css b/packages/form-js-viewer/assets/form-js-base.css
index 06e11eb41..d7045a7c1 100644
--- a/packages/form-js-viewer/assets/form-js-base.css
+++ b/packages/form-js-viewer/assets/form-js-base.css
@@ -934,6 +934,41 @@
margin: 4px 0;
}
+.fjs-container .fjs-repeat-row-container {
+ position: relative;
+}
+
+.fjs-container .fjs-repeat-row-container:focus-within .fjs-repeat-row-delete,
+.fjs-container .fjs-repeat-row-container:hover .fjs-repeat-row-delete-container .fjs-repeat-row-delete,
+.fjs-container .fjs-repeat-row-container .fjs-repeat-row-delete-container:hover .fjs-repeat-row-delete {
+ display: flex;
+}
+
+.fjs-container .fjs-repeat-row-container .fjs-repeat-row-delete-container {
+ display: flex;
+ position: absolute;
+ height: 100px;
+ width: 100px;
+ top: calc(50% - 45px);
+ right: -75px;
+ align-items: center;
+ justify-content: center;
+}
+
+.fjs-container .fjs-repeat-row-container .fjs-repeat-row-delete {
+ display: none;
+ font-family: inherit;
+ font-size: inherit;
+ cursor: pointer;
+ color: var(--color-accent);
+ background: white;
+ border: 2px solid var(--color-accent);
+ height: 24px;
+ width: 24px;
+ align-items: center;
+ justify-content: center;
+}
+
.fjs-container .fjs-repeat-render-footer {
display: flex;
align-items: center;
diff --git a/packages/form-js-viewer/src/Form.js b/packages/form-js-viewer/src/Form.js
index a9270e7ab..ea92ce941 100644
--- a/packages/form-js-viewer/src/Form.js
+++ b/packages/form-js-viewer/src/Form.js
@@ -137,7 +137,7 @@ export default class Form {
warnings
} = this.get('importer').importSchema(schema);
- const initializedData = this._initializeFieldData(clone(data));
+ const initializedData = this._getInitializedFieldData(clone(data));
this._setState({
data: initializedData,
@@ -477,11 +477,16 @@ export default class Form {
/**
* @internal
*/
- _initializeFieldData(data) {
+ _getInitializedFieldData(data, options = {}) {
const formFieldRegistry = this.get('formFieldRegistry');
const formFields = this.get('formFields');
const pathRegistry = this.get('pathRegistry');
+ const {
+ customRoot,
+ customIndexes
+ } = options;
+
function initializeFieldDataRecursively(initializedData, formField, indexes) {
const { defaultValue, type, isRepeating } = formField;
const { config: fieldConfig } = formFields.get(type);
@@ -518,7 +523,16 @@ export default class Form {
// (c) Initialize field value in output data
set(initializedData, valuePath, valueData);
- // (d) Recurse repeatable parents both across the indexes of repetition and the children
+ // (d) If indexed ahead of time, recurse repeatable simply across the children
+ if (!isUndefined(indexes[formField.id])) {
+ formField.components.forEach(
+ (component) => initializeFieldDataRecursively(initializedData, component, { ...indexes })
+ );
+
+ return;
+ }
+
+ // (e) Recurse repeatable parents both across the indexes of repetition and the children
valueData.forEach((_, index) => {
formField.components.forEach(
(component) => initializeFieldDataRecursively(initializedData, component, { ...indexes, [formField.id]: index })
@@ -533,9 +547,17 @@ export default class Form {
}
}
+ // allows definition of a specific subfield to generate the data for
+ const root = customRoot || formFieldRegistry.getForm();
+ const indexes = customIndexes || {};
+ const basePath = pathRegistry.getValuePath(root, { indexes }) || [];
+
+ // if indexing ahead of time, we must add this index to the data path at the end
+ const path = !isUndefined(indexes[root.id]) ? [ ...basePath, indexes[root.id] ] : basePath;
+
const workingData = clone(data);
- initializeFieldDataRecursively(workingData, formFieldRegistry.getForm(), {});
- return workingData;
+ initializeFieldDataRecursively(workingData, root, indexes);
+ return get(workingData, path, {});
}
}
diff --git a/packages/form-js-viewer/src/features/repeatRender/RepeatRenderManager.js b/packages/form-js-viewer/src/features/repeatRender/RepeatRenderManager.js
index d9c5d1ac1..cc255017f 100644
--- a/packages/form-js-viewer/src/features/repeatRender/RepeatRenderManager.js
+++ b/packages/form-js-viewer/src/features/repeatRender/RepeatRenderManager.js
@@ -2,6 +2,7 @@ import { get } from 'min-dash';
import ExpandSvg from '../../render/components/form-fields/icons/Expand.svg';
import CollapseSvg from '../../render/components/form-fields/icons/Collapse.svg';
+import XMarkSvg from '../../render/components/form-fields/icons/XMark.svg';
export default class RepeatRenderManager {
@@ -48,15 +49,34 @@ export default class RepeatRenderManager {
const displayValues = isCollapsed ? values.slice(0, nonCollapsedItems) : values;
+ const onDeleteItem = (index) => {
+
+ const updatedValues = values.slice();
+ updatedValues.splice(index, 1);
+
+ props.onChange({
+ field: repeaterField,
+ value: updatedValues,
+ indexes
+ });
+ };
+
return (
<>
{displayValues.map((_, index) => {
const elementProps = {
...restProps,
- indexes: { ...(indexes || {}), [ repeaterField.id ]: index },
+ indexes: { ...(indexes || {}), [ repeaterField.id ]: index }
};
- return