diff --git a/demo/FormExamples.jsx b/demo/FormExamples.jsx
index b815a31..5a7c9a9 100644
--- a/demo/FormExamples.jsx
+++ b/demo/FormExamples.jsx
@@ -14,6 +14,8 @@ import {
FormGroupAutocompleteTag,
Table,
FormAutocompleteTag,
+ FormGroupTable,
+ Dialog,
// eslint-disable-next-line import/no-unresolved
} from '../dist/main';
@@ -95,6 +97,14 @@ export function FormExamples() {
},
},
],
+ formTable2: [
+ {
+ message: 'Must have more than 2 itens',
+ validate(value) {
+ return value?.length > 2;
+ },
+ },
+ ],
}),
[changeCustomValidation]
);
@@ -761,6 +771,12 @@ export function FormExamples() {
menuClassName="p-4 w-100"
/>
+
FormTable
+
+
+
+
+
@@ -861,3 +877,82 @@ function FormAutocompleteTagsWithCustomLabel() {
);
}
+
+function FormGroupTable1() {
+ return (
+ console.log('formTable', args)}
+ tableProps={{
+ actionLabel: 'Actions',
+ columns: [
+ {
+ attribute: 'name',
+ label: 'Name',
+ },
+ {
+ attribute: 'number',
+ label: 'Number',
+ },
+ ],
+ }}
+ getRemoveComponent={(removeItem) => removeItem()}>}
+ getAddItemComponent={(addItem) => }
+ />
+ );
+}
+function FormGroupTable2() {
+ return (
+ removeItem()}>}
+ getAddItemComponent={(addItem) => }
+ />
+ );
+}
+
+function AddFormGroupTableItem({ addItem }) {
+ return (
+
+ );
+}
diff --git a/demo/UncontrolledFormExamples.jsx b/demo/UncontrolledFormExamples.jsx
index b49eaab..1d83ff3 100644
--- a/demo/UncontrolledFormExamples.jsx
+++ b/demo/UncontrolledFormExamples.jsx
@@ -14,6 +14,8 @@ import {
UncontrolledFormGroupAutocomplete,
UncontrolledFormGroupDropdown,
UncontrolledFormGroupRadio,
+ UncontrolledFormGroupTable,
+ Dialog,
} from '../dist/main';
export function UncontrolledFormExamples() {
@@ -84,6 +86,14 @@ export function UncontrolledFormExamples() {
},
},
],
+ formTable2: [
+ {
+ message: 'Must have more than 2 itens',
+ validate(value) {
+ return value?.length > 2;
+ },
+ },
+ ],
}}
>
Form configuration:
@@ -426,6 +436,12 @@ export function UncontrolledFormExamples() {
+
+ FormTable
+
+
+
+
);
@@ -1095,3 +1111,82 @@ function FormTextareaSetValueTeste2({}) {
);
}
+
+function FormUncontrolledFormGroupTable1() {
+ return (
+ console.log('formTable', args)}
+ tableProps={{
+ actionLabel: 'Actions',
+ columns: [
+ {
+ attribute: 'name',
+ label: 'Name',
+ },
+ {
+ attribute: 'number',
+ label: 'Number',
+ },
+ ],
+ }}
+ getRemoveComponent={(removeItem) => removeItem()}>}
+ getAddItemComponent={(addItem) => }
+ />
+ );
+}
+function FormUncontrolledFormGroupTable2() {
+ return (
+ removeItem()}>}
+ getAddItemComponent={(addItem) => }
+ />
+ );
+}
+
+function AddFormGroupTableItem({ addItem }) {
+ return (
+
+ );
+}
diff --git a/src/forms/FormTable.jsx b/src/forms/FormTable.jsx
new file mode 100644
index 0000000..8026baf
--- /dev/null
+++ b/src/forms/FormTable.jsx
@@ -0,0 +1,193 @@
+import React, { useCallback, useMemo } from 'react';
+import PropTypes from 'prop-types';
+
+import { isFunction } from 'js-var-type';
+
+import { formatClasses } from '../utils/attributes';
+
+import { Table } from '../table/Table';
+
+import { useFormControl } from './helpers/useFormControl';
+import { booleanOrFunction } from './helpers/form-helpers';
+import { FormGroup } from './FormGroup';
+
+/**
+ * FormTable
+ *
+ * This component allows you to control an array of itens in an Form.
+ * This array will be shown as a table.
+ * @param {object} param0
+ * @param {name} param0.name - Name of the field
+ * @param {boolean|Function=} param0.required - Defines whether the field is required for the form or not. If it's a function, the first parameter is the formData
+ * @param {boolean|Function=} param0.disabled - Defines whether the field is disabled for the form or not. If it's a function, the first parameter is the formData
+ * @param {Function=} param0.afterChange - Function that will run after an update on the field
+ * @param {object} param0.tableProps - Props of the "Table" component
+ * @param {Function=} param0.getCustomActions - Function that recieves "item" and "index", and must return an array of Table actions.
+ * @param {Function} param0.getAddItemComponent - Function that recieves the "item to be added" and must return the element that will be used to add new itens on the Table
+ * @param {Function} param0.getRemoveComponent - Function that recieves the "remove item function" and must return the element that will be used to remove the item
+ * @returns {JSX.Element}
+ *
+ * @example
+ *
+ * ```jsx
+ * function FormUncontrolledFormGroupTable() {
+ * return (
+ * console.log('formTable', args)}
+ * tableProps={{
+ * actionLabel: 'Actions',
+ * columns: [
+ * {
+ * attribute: 'name',
+ * label: 'Name',
+ * },
+ * {
+ * attribute: 'number',
+ * label: 'Number',
+ * },
+ * ],
+ * }}
+ * getRemoveComponent={(removeItem) => removeItem()}>}
+ * getAddItemComponent={(addItem) => }
+ * />
+ * );
+ *}
+ *
+ *function AddFormGroupTableItem({ addItem }) {
+ * // Form to generate new itens
+ *
+ * return (
+ *
+ * );
+ *}
+ * ```
+ */
+
+export function FormTable({
+ name,
+ required: _required,
+ disabled: _disabled,
+ afterChange,
+ tableProps,
+ getCustomActions,
+ getAddItemComponent,
+ getRemoveComponent,
+}) {
+ const { getValue, register, getFormData, setValue } = useFormControl(name, 'array');
+ const registerRef = useCallback(register, [register]);
+ const disabled = booleanOrFunction(_disabled, getFormData());
+ const required = booleanOrFunction(_required, getFormData());
+
+ const value = useMemo(() => getValue() || [], [getValue]);
+
+ const removeItem = useCallback(
+ (doc, index) => {
+ const newValue = value?.filter?.((_, i) => i !== index) ?? [];
+
+ setValue(newValue);
+
+ if (isFunction(afterChange)) {
+ afterChange(newValue);
+ }
+ },
+ [afterChange, setValue, value]
+ );
+ const addItem = useCallback(
+ (item) => {
+ const newValue = [...(value || []), item];
+
+ setValue(newValue);
+
+ if (isFunction(afterChange)) {
+ afterChange(newValue);
+ }
+ },
+ [afterChange, setValue, value]
+ );
+
+ const addItemComponent = useMemo(() => getAddItemComponent?.(addItem) ?? <>>, [addItem, getAddItemComponent]);
+
+ const attrs = {
+ disabled,
+ name,
+ required,
+ };
+
+ return (
+ <>
+ 0 ? '1' : ''} //for required validation
+ />
+ {addItemComponent}
+ [
+ ...(getCustomActions?.(doc, index) ?? []),
+ {
+ content: getRemoveComponent(() => removeItem(doc, index)),
+ },
+ ]}
+ docs={value}
+ {...tableProps}
+ >
+ >
+ );
+}
+
+FormTable.defaultProps = {
+ tableProps: {},
+};
+
+const formTableProps = {
+ afterChange: PropTypes.func,
+ disabled: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
+ name: PropTypes.string.isRequired,
+ required: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
+ tableProps: PropTypes.shape(Table.propTypes),
+ getCustomActions: PropTypes.func,
+ getRemoveComponent: PropTypes.func,
+ getAddItemComponent: PropTypes.func,
+};
+
+FormTable.propTypes = formTableProps;
+
+export function FormGroupTable(props) {
+ return (
+
+
+
+ );
+}
+
+FormGroupTable.propTypes = {
+ ...formTableProps,
+ help: PropTypes.node,
+ label: PropTypes.node.isRequired,
+};
diff --git a/src/forms/index.js b/src/forms/index.js
index 2d67b6d..547b1ae 100644
--- a/src/forms/index.js
+++ b/src/forms/index.js
@@ -9,6 +9,7 @@ export * from './FormInput';
export * from './FormRadio';
export * from './FormSelect';
export * from './FormSwitch';
+export * from './FormTable';
export * from './FormTextarea';
export * from './helpers/useFormControl';
export * from './helpers/useFormData';
diff --git a/src/uncontrolled-forms/UncontrolledFormTable.jsx b/src/uncontrolled-forms/UncontrolledFormTable.jsx
new file mode 100644
index 0000000..2c2cb3c
--- /dev/null
+++ b/src/uncontrolled-forms/UncontrolledFormTable.jsx
@@ -0,0 +1,199 @@
+import React, { useCallback, useMemo, useState } from 'react';
+import PropTypes from 'prop-types';
+
+import { isFunction } from 'js-var-type';
+
+import { Table } from '../table/Table';
+import { formatClasses } from '../utils/attributes';
+
+import { booleanOrFunction } from './helpers/form-helpers';
+
+import { useUncontrolledFormControl } from './helpers/useUncontrolledFormControl';
+import { UncontrolledFormGroup } from './UncontrolledFormGroup';
+
+/**
+ * UncontrolledFormTable
+ *
+ * This component allows you to control an array of itens in an UncontrolledForm.
+ * This array will be shown as a table.
+ * @param {object} param0
+ * @param {name} param0.name - Name of the field
+ * @param {boolean|Function=} param0.required - Defines whether the field is required for the form or not. If it's a function, the first parameter is the formData
+ * @param {boolean|Function=} param0.disabled - Defines whether the field is disabled for the form or not. If it's a function, the first parameter is the formData
+ * @param {Function=} param0.afterChange - Function that will run after an update on the field
+ * @param {object} param0.tableProps - Props of the "Table" component
+ * @param {Function=} param0.getCustomActions - Function that recieves "item" and "index", and must return an array of Table actions.
+ * @param {Function} param0.getAddItemComponent - Function that recieves the "item to be added" and must return the element that will be used to add new itens on the Table
+ * @param {Function} param0.getRemoveComponent - Function that recieves the "remove item function" and must return the element that will be used to remove the item
+ * @returns {JSX.Element}
+ *
+ * @example
+ *
+ * ```jsx
+ * function FormUncontrolledFormGroupTable() {
+ * return (
+ * console.log('formTable', args)}
+ * tableProps={{
+ * actionLabel: 'Actions',
+ * columns: [
+ * {
+ * attribute: 'name',
+ * label: 'Name',
+ * },
+ * {
+ * attribute: 'number',
+ * label: 'Number',
+ * },
+ * ],
+ * }}
+ * getRemoveComponent={(removeItem) => removeItem()}>}
+ * getAddItemComponent={(addItem) => }
+ * />
+ * );
+ *}
+ *
+ *function AddFormGroupTableItem({ addItem }) {
+ * // Form to generate new itens
+ *
+ * return (
+ *
+ * );
+ *}
+ * ```
+ */
+
+export function UncontrolledFormTable({
+ name,
+ required: _required,
+ disabled: _disabled,
+ afterChange,
+ tableProps,
+ getCustomActions,
+ getAddItemComponent,
+ getRemoveComponent,
+}) {
+ const state = useState([]);
+
+ const { getValue, getFormData, registerInputRef, setValue } = useUncontrolledFormControl(name, 'array', {
+ state,
+ });
+
+ const value = useMemo(() => getValue(), [getValue]);
+
+ const removeItem = useCallback(
+ (doc, index) => {
+ const newValue = value?.filter?.((_, i) => i !== index) ?? [];
+
+ setValue(newValue);
+
+ if (isFunction(afterChange)) {
+ afterChange(newValue);
+ }
+ },
+ [afterChange, setValue, value]
+ );
+ const addItem = useCallback(
+ (item) => {
+ const newValue = [...(value || []), item];
+
+ setValue(newValue);
+
+ if (isFunction(afterChange)) {
+ afterChange(newValue);
+ }
+ },
+ [afterChange, setValue, value]
+ );
+
+ const addItemComponent = useMemo(() => getAddItemComponent?.(addItem) ?? <>>, [addItem, getAddItemComponent]);
+
+ const disabled = booleanOrFunction(_disabled, getFormData());
+ const required = booleanOrFunction(_required, getFormData());
+
+ const attrs = {
+ disabled,
+ name,
+ required,
+ };
+
+ /** The input is for the default form validation, and will not be shown */
+
+ return (
+ <>
+ 0 ? '1' : ''} //for required validation
+ />
+ {addItemComponent}
+ [
+ ...(getCustomActions?.(doc, index) ?? []),
+ {
+ content: getRemoveComponent(() => removeItem(doc, index)),
+ },
+ ]}
+ docs={value}
+ {...tableProps}
+ >
+ >
+ );
+}
+
+UncontrolledFormTable.defaultProps = {
+ tableProps: {},
+};
+
+const formTableProps = {
+ afterChange: PropTypes.func,
+ disabled: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
+ name: PropTypes.string.isRequired,
+ required: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
+ tableProps: PropTypes.shape(Table.propTypes),
+ getCustomActions: PropTypes.func,
+ getRemoveComponent: PropTypes.func,
+ getAddItemComponent: PropTypes.func,
+};
+
+UncontrolledFormTable.propTypes = formTableProps;
+
+export function UncontrolledFormGroupTable(props) {
+ return (
+
+
+
+ );
+}
+
+UncontrolledFormGroupTable.propTypes = {
+ ...formTableProps,
+ help: PropTypes.node,
+ label: PropTypes.node.isRequired,
+};
diff --git a/src/uncontrolled-forms/helpers/useUncontrolledFormHelper.jsx b/src/uncontrolled-forms/helpers/useUncontrolledFormHelper.jsx
index f44c01e..f599e88 100644
--- a/src/uncontrolled-forms/helpers/useUncontrolledFormHelper.jsx
+++ b/src/uncontrolled-forms/helpers/useUncontrolledFormHelper.jsx
@@ -120,6 +120,10 @@ export function useUncontrolledFormHelper(initialValues, { debounceWait, transfo
if (formControl) {
formControl.setValue(value);
}
+
+ if (validations) {
+ this.validateForm();
+ }
},
setFormControl(name, formControl) {
formHelper.current.setFormControl(name, formControl);
diff --git a/src/uncontrolled-forms/index.jsx b/src/uncontrolled-forms/index.jsx
index fb79daa..a3d410d 100644
--- a/src/uncontrolled-forms/index.jsx
+++ b/src/uncontrolled-forms/index.jsx
@@ -9,6 +9,7 @@ export * from './UncontrolledFormInputMask';
export * from './UncontrolledFormRadio';
export * from './UncontrolledFormSelect';
export * from './UncontrolledFormSwitch';
+export * from './UncontrolledFormTable';
export * from './UncontrolledFormTextarea';
export * from './helpers/useUncontrolledFormControl';
export * from './helpers/useUncontrolledFormEffect';