Skip to content

Commit f3a4d16

Browse files
fix: add support of external validator for JsonEditorEntry
1 parent 1eff2e1 commit f3a4d16

2 files changed

Lines changed: 82 additions & 8 deletions

File tree

src/components/entries/JsonEditor.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88

99
import classnames from 'classnames';
1010

11-
import { isObject } from 'min-dash';
11+
import { isFunction, isObject } from 'min-dash';
1212

1313
import {
1414
useDebounce,
@@ -171,6 +171,7 @@ function JsonEditor(props) {
171171
* @param {boolean} [props.disabled]
172172
* @param {string} [props.placeholder]
173173
* @param {string} [props.tooltip]
174+
* @param {Function} [props.validate]
174175
*/
175176
export default function JsonEditorEntry(props) {
176177
const {
@@ -183,12 +184,16 @@ export default function JsonEditorEntry(props) {
183184
setValue,
184185
disabled,
185186
placeholder,
186-
tooltip
187+
tooltip,
188+
validate
187189
} = props;
188190

189191
const globalError = useError(id);
190192

191193
let value = getValue(element);
194+
const [ localError, setLocalError ] = useState(
195+
() => computeError(validate, value)
196+
);
192197
const [ editorValue, setEditorValue ] = useState(value);
193198

194199
useEffect(() => {
@@ -197,6 +202,7 @@ export default function JsonEditorEntry(props) {
197202
}
198203

199204
setEditorValue(value);
205+
setLocalError(computeError(validate, value));
200206
}, [ value ]);
201207

202208
const onInput = useStaticCallback((newValue) => {
@@ -205,11 +211,14 @@ export default function JsonEditorEntry(props) {
205211
const currentValue = getValue(element);
206212

207213
if (newValue !== currentValue) {
208-
setValue(newValue);
214+
const newValidationError = computeError(validate, newValue);
215+
216+
setValue(newValue, newValidationError);
217+
setLocalError(newValidationError);
209218
}
210219
});
211220

212-
const error = globalError || validateJson(editorValue);
221+
const error = globalError || localError;
213222

214223
return (
215224
<div
@@ -243,6 +252,10 @@ export function isEdited(node) {
243252

244253
// helpers /////////////////
245254

255+
function computeError(validate, value) {
256+
return (isFunction(validate) ? validate(value) : null) || validateJson(value);
257+
}
258+
246259
function validateJson(value) {
247260
if (!value || !value.trim()) return null;
248261

@@ -252,6 +265,3 @@ function validateJson(value) {
252265
return 'JSON contains errors';
253266
}
254267
}
255-
256-
257-

test/spec/components/JsonEditor.spec.js

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,68 @@ describe('<JsonEditor>', function() {
266266
expect(editorInlineErrors).to.not.exist;
267267
});
268268

269+
270+
it('should show error from validate prop', async function() {
271+
272+
// given
273+
const validate = (value) => value === 'invalid' ? 'custom error' : null;
274+
275+
const result = createJsonEditor({
276+
container,
277+
getValue: () => 'invalid',
278+
validate
279+
});
280+
281+
// then
282+
await waitFor(() => {
283+
const error = domQuery('.bio-properties-panel-error', result.container);
284+
expect(error).to.exist;
285+
expect(error.textContent).to.equal('custom error');
286+
});
287+
});
288+
289+
290+
it('should show no error from validate prop if valid', async function() {
291+
292+
// given
293+
const validate = (value) => value === 'invalid' ? 'custom error' : null;
294+
295+
const result = createJsonEditor({
296+
container,
297+
getValue: () => '{"valid": true}',
298+
validate
299+
});
300+
301+
// then
302+
await waitFor(() => {
303+
const error = domQuery('.bio-properties-panel-error', result.container);
304+
expect(error).to.not.exist;
305+
});
306+
});
307+
308+
309+
it('should pass validation error to setValue', async function() {
310+
311+
// given
312+
const validate = () => 'always invalid';
313+
const setValue = sinonSpy();
314+
315+
const result = createJsonEditor({
316+
container,
317+
getValue: () => '',
318+
setValue,
319+
validate
320+
});
321+
322+
// when
323+
setEditorValue(result.container, 'new value');
324+
325+
// then
326+
await waitFor(() => {
327+
expect(setValue).to.have.been.calledWith('new value', 'always invalid');
328+
});
329+
});
330+
269331
});
270332

271333

@@ -349,6 +411,7 @@ function createJsonEditor(options = {}, renderFn = render) {
349411
disabled,
350412
placeholder,
351413
tooltip,
414+
validate,
352415
descriptionConfig = {},
353416
getDescriptionForId = noop,
354417
container,
@@ -389,7 +452,8 @@ function createJsonEditor(options = {}, renderFn = render) {
389452
setValue={ setValue }
390453
disabled={ disabled }
391454
placeholder={ placeholder }
392-
tooltip={ tooltip } />
455+
tooltip={ tooltip }
456+
validate={ validate } />
393457
</DescriptionContext.Provider>
394458
</PropertiesPanelContext.Provider>
395459
</EventContext.Provider>

0 commit comments

Comments
 (0)