Skip to content

Commit

Permalink
wip: feel variable context
Browse files Browse the repository at this point in the history
  • Loading branch information
Skaiir committed Sep 24, 2023
1 parent 8305ecb commit 315fe96
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default class RepeatRenderManager {

Repeater(props) {

const { RowsRenderer, indexes, useSharedState, ...restProps } = props;
const { RowsRenderer, indexes, useSharedState, variableContext: parentVariableContext, ...restProps } = props;

const [ sharedRepeatState ] = useSharedState;

Expand Down Expand Up @@ -63,10 +63,15 @@ export default class RepeatRenderManager {

return (
<>
{displayValues.map((_, index) => {
{displayValues.map((value, index) => {
const elementProps = {
...restProps,
indexes: { ...(indexes || {}), [ repeaterField.id ]: index }
indexes: { ...(indexes || {}), [ repeaterField.id ]: index },
variableContext: {
this: value,
parent: parentVariableContext,
i: [ ...parentVariableContext.i , index ]
}
};

return <div class="fjs-repeat-row-container">
Expand Down
13 changes: 12 additions & 1 deletion packages/form-js-viewer/src/render/components/FormComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import FormField from './FormField';
import PoweredBy from './PoweredBy';

import useService from '../hooks/useService';
import { useMemo } from 'preact/hooks';
import { useFilteredFormData } from '../hooks';

const noop = () => {};

export default function FormComponent(props) {
const form = useService('form');

const { schema, properties } = form._getState();
const { schema, properties, data } = form._getState();

Check failure on line 14 in packages/form-js-viewer/src/render/components/FormComponent.js

View workflow job for this annotation

GitHub Actions / Build (ubuntu-20.04, 20)

'data' is assigned a value but never used. Allowed unused vars must match /^_/u

Check failure on line 14 in packages/form-js-viewer/src/render/components/FormComponent.js

View workflow job for this annotation

GitHub Actions / Build (ubuntu-20.04, 20)

'data' is assigned a value but never used. Allowed unused vars must match /^_/u

const { ariaLabel } = properties;

Expand All @@ -31,6 +33,14 @@ export default function FormComponent(props) {
onReset();
};

const filteredFormData = useFilteredFormData();

const variableContext = useMemo(() => ({
parent: null,
this: filteredFormData,
i: []
}), [ filteredFormData ]);

return (
<form
class="fjs-form"
Expand All @@ -41,6 +51,7 @@ export default function FormComponent(props) {
>
<FormField
field={ schema }
variableContext={ variableContext }
onChange={ onChange }
/>

Expand Down
3 changes: 2 additions & 1 deletion packages/form-js-viewer/src/render/components/Label.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ export default function Label(props) {
const {
id,
label,
variableContext,
collapseOnEmpty = true,
required = false
} = props;

const evaluatedLabel = useSingleLineTemplateEvaluation(label || '', { debug: true });
const evaluatedLabel = useSingleLineTemplateEvaluation(label || '', { debug: true, variableContext });

return (
<label for={ id } class={ classNames('fjs-form-field-label', { 'fjs-incollapsible-label': !collapseOnEmpty }, props['class']) }>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default function Checkbox(props) {
disabled,
errors = [],
errorMessageId,
variableContext,
onBlur,
field,
readonly,
Expand Down Expand Up @@ -47,6 +48,7 @@ export default function Checkbox(props) {
return <div class={ classNames(formFieldClasses(type, { errors, disabled, readonly }), { 'fjs-checked': value }) }>
<Label
id={ prefixId(id, formId) }
variableContext={ variableContext }
label={ label }
required={ required }>
<input
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,49 @@ import { useMemo } from 'preact/hooks';
/**
* Evaluate a string reactively based on the expressionLanguage and form data.
* If the string is not an expression, it is returned as is.
* Memoised to minimize re-renders.
*
* @param {string} value
* The function is memoized to minimize re-renders.
*
* @param {string} value - The string to evaluate.
* @param {Object} options - Additional options, such as variableContext.
* @returns {any} - Evaluated value or the original value if not an expression.
*/
export default function useExpressionEvaluation(value) {
export default function useExpressionEvaluation(value, options = {}) {

const { variableContext } = options;
const formData = useFilteredFormData();
const expressionLanguage = useService('expressionLanguage');

return useMemo(() => {
// Create the full form data, injecting variableContext if present
const fullFormData = useMemo(() => {
if (variableContext) {
return {
...variableContext,
formData,
..._buildFallbackAccessors(variableContext)
};
}
return formData;
}, [ formData, variableContext ]);

return useMemo(() => {
if (expressionLanguage && expressionLanguage.isExpression(value)) {
return expressionLanguage.evaluate(value, formData);
return expressionLanguage.evaluate(value, fullFormData);
}

return value;

}, [ expressionLanguage, formData, value ]);
}, [ expressionLanguage, fullFormData, value ]);
}

/**
* Build fallback accessors by transforming object keys.
* Adds underscores around each key.
*
* @param {Object} obj - The original object.
* @returns {Object} - New object with transformed keys.
*/
const _buildFallbackAccessors = (obj) => {
const newObj = {};
for (const [ key, value ] of Object.entries(obj)) {
newObj[`_${key}_`] = value;
}
return newObj;
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { useMemo } from 'preact/hooks';
* @param {boolean} [options.debug = false]
* @param {boolean} [options.strict = false]
* @param {Function} [options.buildDebugString]
* @param {Object} [options.variableContext]
*
*/
export default function useSingleLineTemplateEvaluation(value, options = {}) {
Expand Down
30 changes: 24 additions & 6 deletions packages/form-js-viewer/src/render/hooks/useTemplateEvaluation.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,37 @@ import { useMemo } from 'preact/hooks';
* @param {boolean} [options.debug = false]
* @param {boolean} [options.strict = false]
* @param {Function} [options.buildDebugString]
* @param {Object} [options.variableContext]
*
*/
export default function useTemplateEvaluation(value, options) {
export default function useTemplateEvaluation(value, options = {}) {
const filteredData = useFilteredFormData();
const templating = useService('templating');
const { variableContext } = options;

return useMemo(() => {
const fullData = useMemo(() => {
if (variableContext) {
return {
...variableContext,
...filteredData,
..._buildFallbackAccessors(variableContext)
};
}
return filteredData;
}, [ filteredData, variableContext ]);

return useMemo(() => {
if (templating && templating.isTemplate(value)) {
return templating.evaluate(value, filteredData, options);
return templating.evaluate(value, fullData, options);
}

return value;

}, [ filteredData, templating, value, options ]);
}, [ fullData, templating, value, options ]);
}

const _buildFallbackAccessors = (obj) => {
const newObj = {};
for (const [ key, value ] of Object.entries(obj)) {
newObj[`_${key}_`] = value;
}
return newObj;
};

0 comments on commit 315fe96

Please sign in to comment.