Skip to content

Commit f8791c0

Browse files
committed
Add onSubmitError
1 parent d802845 commit f8791c0

File tree

13 files changed

+77
-27
lines changed

13 files changed

+77
-27
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ Form generation features include the following:
5656
| array: items | This schema is used to render each subsection of the array. Tuple validation (where items is a list of schemas) is not supported. |
5757
| array: contains | Not supported except for validation |
5858
| array: additionalItems | Not supported |
59-
| array: length | Implemented only as validation |
59+
| array: maxItems | Implemented only as validation |
60+
| array: minItems | Implemented only as validation |
6061
| array: uniqueItems | Implemented as validation |
6162
| generic: title | The label of a field uses title for preference, otherwise it defaults to convering camel case into separated words e.g. initialRepeatingCost -> Initial repeating cost |
6263
| generic: description | Description is rendered as part of the label and can be styled differently |
@@ -102,7 +103,7 @@ Here are the built-in editors:
102103
| textarea | string | Renders a textarea HTML tag rather than an input for text entry |
103104
| currency | number | Renders a text entry box with an automatic currency label (set with the currencySymbol property on the top-level schema object). Supplies a decimal number to the output value. |
104105
| hidden | string | Renders a type='hidden' text box |
105-
| multicheck | array of enums | Renders a multi-select set of check boxes which supplies an array of values of an enum whose values correspond to the check box labels |
106+
| multiCheck | array of enums | Renders a multi-select set of check boxes which supplies an array of values of an enum whose values correspond to the check box labels |
106107
| upload | string | Renders a file upload. The behaviour of the file upload is determined by two functions set up on the componentContext prop which (see below) is an object containing customisation for components. The functions are:
107108

108109

build/components/schema-paged-form.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import React from 'react';
22
import { ISchemaFormProps } from 'components/schema-form';
3+
import { ErrorObject } from 'error';
34
export interface ISchemaPagedFormProps extends ISchemaFormProps {
45
onSubmit?(value: object, page: number): void;
6+
onSubmitError?(value: object, page: number, errors: ErrorObject): void;
57
onPage?(value: object, page: number, previousPage: number): void;
68
makeNextLink(nextPage: number, onClick: (page: number) => void): React.ReactNode;
79
makePreviousLink(previousPage: number, onClick: (page: number) => void): React.ReactNode;

build/components/schema-submit-form.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import React from 'react';
22
import { ISchemaFormProps } from 'components/schema-form';
3+
import { ErrorObject } from 'error';
34
export interface ISchemaSubmitFormProps extends ISchemaFormProps {
45
onSubmit?(value: object): Promise<boolean>;
6+
onSubmitError?(value: object, error: ErrorObject): void;
57
makeSubmitLink(onClick: () => void): React.ReactNode;
68
onDirty?(isDirty: boolean): void;
79
}

build/editors/upload-editor.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export interface IUploadEditorContext {
55
sendFile(url: string, file: File, progress: (pc: number) => void): Promise<void>;
66
deleteFile?(url: string): Promise<void>;
77
saveSiteRelative: boolean;
8+
testState?: "uploading";
89
}
910
export declare function sendFileAsBody(url: string, file: File, progress: (pc: number) => void, method?: string): Promise<void>;
1011
export declare const imageSpec: {

build/index.es.js

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18216,7 +18216,8 @@ function SchemaFormArray(_a) {
1821618216
var collapsible = (context.collapsible && path.length > 0) || false;
1821718217
var onCollapserClick = function () { return setCollapsed(function (collapsed) { return !collapsed; }); };
1821818218
var collapserClasses = "sf-collapser " + (collapsed ? "sf-collapsed" : "sf-open");
18219-
var showTitle = path.length > 0;
18219+
var caption = fieldCaption(schema, path);
18220+
var showTitle = path.length > 0 && (collapsible || caption);
1822018221
return (React.createElement("div", { className: arrayClass },
1822118222
showTitle && React.createElement("div", { className: "sf-title" },
1822218223
collapsible && React.createElement("span", { className: collapserClasses, onClick: onCollapserClick }),
@@ -18264,7 +18265,8 @@ function SchemaFormObject(_a) {
1826418265
var collapsible = (context.collapsible && path.length > 0) || false;
1826518266
var onCollapserClick = function () { return setCollapsed(function (collapsed) { return !collapsed; }); };
1826618267
var collapserClasses = "sf-collapser " + (collapsed ? "sf-collapsed" : "sf-open");
18267-
var showTitle = path.length > 0;
18268+
var caption = fieldCaption(schema, path);
18269+
var showTitle = path.length > 0 && (collapsible || caption);
1826818270
return (React.createElement("div", { className: objectClass },
1826918271
showTitle && React.createElement("div", { className: "sf-title" },
1827018272
collapsible && React.createElement("span", { className: collapserClasses, onClick: onCollapserClick }),
@@ -20571,9 +20573,14 @@ function UploadEditor(props) {
2057120573
var context = props.context, schema = props.schema, path = props.path, value = props.value, errors = props.errors, onFocus = props.onFocus;
2057220574
var isMulti = schema['editor'].toLowerCase().indexOf('multi') >= 0;
2057320575
var uploadMsg = "Drag files here or click to select";
20574-
var uploadContext = (context || {});
20576+
var uploadContext = ((context && context['uploadEditor']) || {});
2057520577
var _a = useReducer(progressBarsReducer, {}), progressBars = _a[0], dispatchProgressBars = _a[1];
2057620578
var dispatch = useContext(ValueDispatch);
20579+
useEffect(function () {
20580+
if (uploadContext.testState) {
20581+
dispatchProgressBars(['test', 50]);
20582+
}
20583+
}, [uploadContext.testState]);
2057720584
var updateProgress = function (file, pc) {
2057820585
dispatchProgressBars([file.name, pc]);
2057920586
};
@@ -27987,8 +27994,9 @@ function SchemaForm(props) {
2798727994
function SchemaSubmitForm(props) {
2798827995
var onDirty = props.onDirty, onChange = props.onChange, schema = props.schema, value = props.value;
2798927996
var _a = useState(value), currentValue = _a[0], setCurrentValue = _a[1];
27990-
var _b = useState(false), submitted = _b[0], setSubmitted = _b[1];
27991-
var _c = useState(false), dirty = _c[0], setDirty = _c[1];
27997+
var _b = useState(new ErrorObject()), currentErrors = _b[0], setCurrentErrors = _b[1];
27998+
var _c = useState(false), submitted = _c[0], setSubmitted = _c[1];
27999+
var _d = useState(false), dirty = _d[0], setDirty = _d[1];
2799228000
// feed value into state when props change
2799328001
useEffect(function () {
2799428002
if (!lodash.isEqual(currentValue, value)) {
@@ -28000,6 +28008,11 @@ function SchemaSubmitForm(props) {
2800028008
console.log('value changed, set clean');
2800128009
}
2800228010
}, [value]);
28011+
useEffect(function () {
28012+
if (!isEmpty(currentErrors) && props.onSubmitError) {
28013+
props.onSubmitError(currentValue, currentErrors);
28014+
}
28015+
}, [currentErrors, submitted]);
2800328016
var handleChange = useCallback(function (value, path, errors) {
2800428017
setCurrentValue(value);
2800528018
if (!dirty && onDirty)
@@ -28014,6 +28027,7 @@ function SchemaSubmitForm(props) {
2801428027
function onSubmit() {
2801528028
setSubmitted(true);
2801628029
var newErrors = validate(schema, currentValue, new SchemaContext(schema));
28030+
setCurrentErrors(newErrors);
2801728031
if (props.onSubmit && isEmpty(newErrors)) {
2801828032
props.onSubmit(currentValue)
2801928033
.then(function (submitted) {
@@ -28084,9 +28098,8 @@ function SchemaPagedForm(props) {
2808428098
if (props.onSubmit && isEmpty(errors)) {
2808528099
props.onSubmit(value, props.page);
2808628100
}
28087-
else if (props.onSubmit) {
28088-
console.log('+ Blocked page change from error:');
28089-
console.log(JSON.parse(JSON.stringify(errors)));
28101+
else if (!isEmpty(errors) && props.onSubmitError) {
28102+
props.onSubmitError(value, props.page, errors);
2809028103
}
2809128104
}
2809228105
var pageLast = Object.keys(props.schema['properties']).reduce(function (currCount, key) {

build/index.es.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/index.js

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18223,7 +18223,8 @@ function SchemaFormArray(_a) {
1822318223
var collapsible = (context.collapsible && path.length > 0) || false;
1822418224
var onCollapserClick = function () { return setCollapsed(function (collapsed) { return !collapsed; }); };
1822518225
var collapserClasses = "sf-collapser " + (collapsed ? "sf-collapsed" : "sf-open");
18226-
var showTitle = path.length > 0;
18226+
var caption = fieldCaption(schema, path);
18227+
var showTitle = path.length > 0 && (collapsible || caption);
1822718228
return (React__default.createElement("div", { className: arrayClass },
1822818229
showTitle && React__default.createElement("div", { className: "sf-title" },
1822918230
collapsible && React__default.createElement("span", { className: collapserClasses, onClick: onCollapserClick }),
@@ -18271,7 +18272,8 @@ function SchemaFormObject(_a) {
1827118272
var collapsible = (context.collapsible && path.length > 0) || false;
1827218273
var onCollapserClick = function () { return setCollapsed(function (collapsed) { return !collapsed; }); };
1827318274
var collapserClasses = "sf-collapser " + (collapsed ? "sf-collapsed" : "sf-open");
18274-
var showTitle = path.length > 0;
18275+
var caption = fieldCaption(schema, path);
18276+
var showTitle = path.length > 0 && (collapsible || caption);
1827518277
return (React__default.createElement("div", { className: objectClass },
1827618278
showTitle && React__default.createElement("div", { className: "sf-title" },
1827718279
collapsible && React__default.createElement("span", { className: collapserClasses, onClick: onCollapserClick }),
@@ -20578,9 +20580,14 @@ function UploadEditor(props) {
2057820580
var context = props.context, schema = props.schema, path = props.path, value = props.value, errors = props.errors, onFocus = props.onFocus;
2057920581
var isMulti = schema['editor'].toLowerCase().indexOf('multi') >= 0;
2058020582
var uploadMsg = "Drag files here or click to select";
20581-
var uploadContext = (context || {});
20583+
var uploadContext = ((context && context['uploadEditor']) || {});
2058220584
var _a = React.useReducer(progressBarsReducer, {}), progressBars = _a[0], dispatchProgressBars = _a[1];
2058320585
var dispatch = React.useContext(ValueDispatch);
20586+
React.useEffect(function () {
20587+
if (uploadContext.testState) {
20588+
dispatchProgressBars(['test', 50]);
20589+
}
20590+
}, [uploadContext.testState]);
2058420591
var updateProgress = function (file, pc) {
2058520592
dispatchProgressBars([file.name, pc]);
2058620593
};
@@ -27994,8 +28001,9 @@ function SchemaForm(props) {
2799428001
function SchemaSubmitForm(props) {
2799528002
var onDirty = props.onDirty, onChange = props.onChange, schema = props.schema, value = props.value;
2799628003
var _a = React.useState(value), currentValue = _a[0], setCurrentValue = _a[1];
27997-
var _b = React.useState(false), submitted = _b[0], setSubmitted = _b[1];
27998-
var _c = React.useState(false), dirty = _c[0], setDirty = _c[1];
28004+
var _b = React.useState(new ErrorObject()), currentErrors = _b[0], setCurrentErrors = _b[1];
28005+
var _c = React.useState(false), submitted = _c[0], setSubmitted = _c[1];
28006+
var _d = React.useState(false), dirty = _d[0], setDirty = _d[1];
2799928007
// feed value into state when props change
2800028008
React.useEffect(function () {
2800128009
if (!lodash.isEqual(currentValue, value)) {
@@ -28007,6 +28015,11 @@ function SchemaSubmitForm(props) {
2800728015
console.log('value changed, set clean');
2800828016
}
2800928017
}, [value]);
28018+
React.useEffect(function () {
28019+
if (!isEmpty(currentErrors) && props.onSubmitError) {
28020+
props.onSubmitError(currentValue, currentErrors);
28021+
}
28022+
}, [currentErrors, submitted]);
2801028023
var handleChange = React.useCallback(function (value, path, errors) {
2801128024
setCurrentValue(value);
2801228025
if (!dirty && onDirty)
@@ -28021,6 +28034,7 @@ function SchemaSubmitForm(props) {
2802128034
function onSubmit() {
2802228035
setSubmitted(true);
2802328036
var newErrors = validate(schema, currentValue, new SchemaContext(schema));
28037+
setCurrentErrors(newErrors);
2802428038
if (props.onSubmit && isEmpty(newErrors)) {
2802528039
props.onSubmit(currentValue)
2802628040
.then(function (submitted) {
@@ -28091,9 +28105,8 @@ function SchemaPagedForm(props) {
2809128105
if (props.onSubmit && isEmpty(errors)) {
2809228106
props.onSubmit(value, props.page);
2809328107
}
28094-
else if (props.onSubmit) {
28095-
console.log('+ Blocked page change from error:');
28096-
console.log(JSON.parse(JSON.stringify(errors)));
28108+
else if (!isEmpty(errors) && props.onSubmitError) {
28109+
props.onSubmitError(value, props.page, errors);
2809728110
}
2809828111
}
2809928112
var pageLast = Object.keys(props.schema['properties']).reduce(function (currCount, key) {

build/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/schema-form-array.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ export function SchemaFormArray({
5959
const collapsible = (context.collapsible && path.length > 0) || false;
6060
const onCollapserClick = () => setCollapsed(collapsed => !collapsed);
6161
const collapserClasses = "sf-collapser " + (collapsed ? "sf-collapsed" : "sf-open");
62-
const showTitle = path.length > 0;
62+
const caption = fieldCaption(schema, path);
63+
const showTitle = path.length > 0 && (collapsible || caption);
6364

6465
return (
6566
<div className={arrayClass}>

src/components/schema-form-object.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ export function SchemaFormObject({
6969
const collapsible = (context.collapsible && path.length > 0) || false;
7070
const onCollapserClick = () => setCollapsed(collapsed => !collapsed);
7171
const collapserClasses = "sf-collapser " + (collapsed ? "sf-collapsed" : "sf-open");
72-
const showTitle = path.length > 0;
72+
const caption = fieldCaption(schema, path);
73+
const showTitle = path.length > 0 && (collapsible || caption);
7374

7475
return (
7576
<div className={objectClass}>

0 commit comments

Comments
 (0)