-
Notifications
You must be signed in to change notification settings - Fork 391
ArrayControl - Delete Button - Vanilla Renderer #2008
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
Comments
Hi @rsoika, The first approach did not work because the data was modified directly, i.e. In the JSON Forms mappings we expose the update of the managed state via the Regarding rendering: I would like to suggest to use a "header" structure like this:
Of course the class name should ideally not be hard coded but derived from the class system. This structure is more future proof as usually the |
Yes, I have already tried the removeItems method but this did not work. The code looks currently like this: <div className={classNames.children}>
{data ? (
range(0, data.length).map(index => {
const childPath = composePaths(path, `${index}`);
return (
<div><JsonFormsDispatch
schema={schema}
uischema={childUiSchema || uischema}
path={childPath}
key={childPath}
renderers={renderers}
/><button
aria-label={`Delete`}
onClick={() => {
if (window.confirm('Are you sure you wish to delete this item?')) {
removeItems(path,[index]);
}
}}>Delete</button></div>
);
})
) : (
<p>No data</p>
)}
</div> But In the TableArrayControl.txs the method is wrapped by the a method call like this: confirmDelete = (path: string, index: number) => {
const p = path.substring(0, path.lastIndexOf(('.')));
this.props.removeItems(p, [index])();
}; The question for me is: what is |
In the Looking at the code there is a small difference and this is probably why it's not working for you. In the "current code" it looks like this:
while in the code which is working it looks like this:
Explanation:
Now in the invocations here it's not used like this but wrapped into an own function. Therefore now you need to call the actual function which was generated, i.e. you need to invoke |
yes, this is working:
I was not aware that removeItems is a function generator and I have overseen the sufix (); ....As an old Java developer, I fear I will never have the chance to recognize the 'beauty' of this kind of coding... ;-) I will now prepare my pullRequest.... |
sorry, once again:
The declaration of the two methods in the Here is the current complete code import range from 'lodash/range';
import React, { useMemo } from 'react';
import { ArrayControlProps, composePaths, createDefaultValue, findUISchema, Helpers, ControlElement } from '@jsonforms/core';
import { JsonFormsDispatch } from '@jsonforms/react';
import { VanillaRendererProps } from '../../index';
const { convertToValidClassName } = Helpers;
export const ArrayControl = ({
classNames,
data,
label,
path,
schema,
errors,
addItem,
removeItems,
moveUp,
moveDown,
uischema,
uischemas,
getStyleAsClassName,
renderers,
rootSchema
}: ArrayControlProps & VanillaRendererProps) => {
const controlElement = uischema as ControlElement;
const childUiSchema = useMemo(
() => findUISchema(uischemas, schema, uischema.scope, path, undefined, uischema, rootSchema),
[uischemas, schema, uischema.scope, path, uischema, rootSchema]
);
const isValid = errors.length === 0;
const validationClass = getStyleAsClassName('array.control.validation');
const divClassNames = [validationClass]
.concat(isValid ? '' : getStyleAsClassName('array.control.validation.error'))
.join(' ');
const buttonClass = getStyleAsClassName('array.control.button');
const labelClass = getStyleAsClassName('array.control.label');
const controlClass = [
getStyleAsClassName('array.control'),
convertToValidClassName(controlElement.scope)
].join(' ');
return (
<div className={controlClass}>
<header>
<label className={labelClass}>{label}</label>
<button
className={buttonClass}
onClick={addItem(path, createDefaultValue(schema))}
>Add to {label}
</button>
</header>
<div className={divClassNames}>
{errors}
</div>
<div className={classNames.children}>
{data ? (
range(0, data.length).map(index => {
const childPath = composePaths(path, `${index}`);
return (
<div><JsonFormsDispatch
schema={schema}
uischema={childUiSchema || uischema}
path={childPath}
key={childPath}
renderers={renderers}
/><button
aria-label={`Delete`}
onClick={() => {
if (window.confirm('Are you sure you wish to delete this item?')) {
removeItems(path,[index])();
}
}}>Delete</button>
<button
aria-label={`Up`}
onClick={() => {
if (window.confirm('Are you sure you wish to move this item up?')) {
moveUp(path,0)();
}
}}>Up</button>
<button
aria-label={`Down`}
onClick={() => {
if (window.confirm('Are you sure you wish to move this item down?')) {
moveDown(path,0)();
}
}}>Down</button>
</div>
);
})
) : (
<p>No data</p>
)}
</div>
</div>
);
}; |
I invested more time but I can't find out why the runtime complains about that moveUp/moveDown is not a function The only thing I found was that the util/array.ts declares methods with the same name in line 35 |
I think the problem is not in the posted code but in ArrayControlRenderer as this is actually the renderer which is bound against the JSON Forms React bindings and then hands over all its props to the Actually I don't think this separation of Note that:
This is not really a Javascript pattern but just bad naming on our part, lol. They should really be named |
Yes you were right (of course) - the problem was the missing definitions in the ArrayControlRenderer. Thanks, now I can start putting all together...
I will also try to merge both classes into one component file.... |
Now I think my new version should be fine. Please take a look at my new pull request: |
Closed via #2011 |
Is your feature request related to a problem? Please describe.
I am trying now implement the delete button functionality for the
ArrayControl
in the Vanilla Renderer. But this seems to be more difficult as expected.Describe the solution you'd like
My most naive approach was to simple add delete button around the
JsonFormsDispatch
:Technical this works, but the component is not rerendered.
Describe alternatives you've considered
The
TableArrayControl
instead used an methodremoveItems
wrapped by a methodconfirmDelete
The button triggers this method:
I tried to use somehow the
removeItems
method but I did not succeed because of the missing props. At least I did not find out how to build a similar variable in theArrayControl
.Can you please give me a hint what the correct approach would be so that I can prepare a pull request.
Framework
React
RendererSet
Vanilla
Additional context
No response
The text was updated successfully, but these errors were encountered: