Skip to content

Commit

Permalink
Merge pull request #364 from suvarnakale/shiksha-2.0
Browse files Browse the repository at this point in the history
Issue #PS-1249 feat:UI of form fields to show form
  • Loading branch information
itsvick authored Jul 9, 2024
2 parents bb2f3ee + 7b77c53 commit 98a6314
Show file tree
Hide file tree
Showing 5 changed files with 440 additions and 3 deletions.
50 changes: 50 additions & 0 deletions src/components/CustomRadioWidget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import Radio from '@mui/material/Radio';
import RadioGroup from '@mui/material/RadioGroup';
import FormControlLabel from '@mui/material/FormControlLabel';
import FormLabel from '@mui/material/FormLabel';
import { WidgetProps } from '@rjsf/utils';

interface CustomRadioWidgetProps {
value: string;
id: string;
required: boolean;
disabled: boolean;
readonly: boolean;
label: string;
options: any;
onChange: any;
}
const CustomRadioWidget: React.FC<WidgetProps> = ({
id,
value,
required,
disabled,
readonly,
label,
options,
onChange,
}) => {
const handleChange = (event: any) => {
onChange(event.target.value);
};

return (
<div>
<FormLabel component="legend">{label}</FormLabel>
<RadioGroup id={id} value={value} onChange={handleChange} row>
{options?.enumOptions?.map((option: any) => (
<FormControlLabel
key={option.value}
value={option.value}
control={<Radio />}
label={option.label}
disabled={disabled || readonly}
/>
))}
</RadioGroup>
</div>
);
};

export default CustomRadioWidget;
44 changes: 41 additions & 3 deletions src/components/DynamicForm.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import React from 'react';
import React, { useRef } from 'react';
import { IChangeEvent } from '@rjsf/core';
import ISubmitEvent from '@rjsf/core';
import validator from '@rjsf/validator-ajv8';
import { Theme as MaterialUITheme } from '@rjsf/mui';
import { withTheme } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import MultiSelectCheckboxes from './MultiSelectCheckboxes';
import CustomCheckboxWidget from './CustomCheckboxWidget';
import CustomRadioWidget from './CustomRadioWidget';
import CustomErrorList from './CustomErrorList';
import { RJSFSchema, WidgetProps } from '@rjsf/utils';

const FormWithMaterialUI = withTheme(MaterialUITheme);

Expand All @@ -19,6 +23,9 @@ interface DynamicFormProps {
onChange: (event: IChangeEvent<any>) => void;
onError: (errors: any) => void;
showErrorList: boolean;
widgets: {
[key: string]: React.FC<WidgetProps<any, RJSFSchema, any>>;
};
}
const DynamicForm: React.FC<DynamicFormProps> = ({
schema,
Expand All @@ -28,17 +35,48 @@ const DynamicForm: React.FC<DynamicFormProps> = ({
onChange,
onError,
}) => {
const widgets = {
MultiSelectCheckboxes: MultiSelectCheckboxes,
CustomCheckboxWidget: CustomCheckboxWidget,
CustomRadioWidget: CustomRadioWidget,
};
console.log('CustomErrorList', CustomErrorList);

const handleError = (errors: any) => {
if (errors.length > 0) {
// Adjust the selector based on the actual structure of the form element names
const property = errors[0].property.replace(/^root\./, '');
const errorField = document.querySelector(
`[name$="${property}"]`
) as HTMLElement;

if (errorField) {
errorField.focus();
} else {
// If the name-based selector fails, try to select by ID as a fallback
const fallbackField = document.getElementById(property) as HTMLElement;
if (fallbackField) {
fallbackField.focus();
}
}
}
onError(errors);
};

return (
<FormWithMaterialUI
schema={schema}
uiSchema={uiSchema}
formData={formData}
onChange={onChange}
onSubmit={onSubmit}
onError={onError}
validator={validator}
liveValidate
showErrorList={false}
widgets={widgets}
noHtml5Validate
onError={handleError}
// ErrorList={CustomErrorList}
/>
);
};
Expand Down
78 changes: 78 additions & 0 deletions src/components/MultiSelectCheckboxes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React from 'react';
import {
FormControl,
FormControlLabel,
FormGroup,
FormLabel,
Checkbox,
Grid,
} from '@mui/material';
import { WidgetProps } from '@rjsf/utils';

interface CustomMultiselectCheckboxesProps {
label: string;
value: any;
id: string;
required: boolean;
disabled: boolean;
readonly: boolean;
options: any;
onChange: any;
schema: any;
}
const MultiSelectCheckboxes: React.FC<WidgetProps> = ({
schema,
options,
value,
required,
disabled,
readonly,
onChange,
label,
}) => {
const handleChange = (event: any) => {
const { value: optionValue } = event.target;
if (event.target.checked) {
onChange([...value, optionValue]);
} else {
onChange(value.filter((v: any) => v !== optionValue));
}
};

return (
<FormControl component="fieldset" disabled={disabled || readonly}>
<FormLabel
required={required}
component="legend"
style={{ color: 'inherit' }}
>
{label || schema?.title}
</FormLabel>
<FormGroup>
{options?.enumOptions?.map((option: any) => (
<Grid
container
key={option.value}
alignItems="center"
justifyContent="space-between"
style={{ color: 'inherit' }}
>
<Grid item xs={10}>
<FormLabel style={{ color: 'inherit' }}>{option.label}</FormLabel>
</Grid>
<Grid item xs={2}>
<Checkbox
style={{ color: 'inherit' }}
checked={value.includes(option.value)}
onChange={handleChange}
value={option.value}
/>
</Grid>
</Grid>
))}
</FormGroup>
</FormControl>
);
};

export default MultiSelectCheckboxes;
55 changes: 55 additions & 0 deletions src/pages/addLearner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import DynamicForm from '@/components/DynamicForm';
import React from 'react';
import { schema, uiSchema } from '@/utils/schema';
import { IChangeEvent } from '@rjsf/core';
import ISubmitEvent from '@rjsf/core';
import { Box } from '@mui/material';
import { RJSFSchema } from '@rjsf/utils';

const addLearner = () => {
const handleSubmit = (
data: IChangeEvent<any, RJSFSchema, any>,
event: React.FormEvent<any>
) => {
const target = event.target as HTMLFormElement;
const elementsArray = Array.from(target.elements);

for (const element of elementsArray) {
if (
(element instanceof HTMLInputElement ||
element instanceof HTMLSelectElement ||
element instanceof HTMLTextAreaElement) &&
(element.value === '' ||
(Array.isArray(element.value) && element.value.length === 0))
) {
element.focus();
return;
}
}
console.log('Form data submitted:', data.formData);
};

const handleChange = (event: IChangeEvent<any>) => {
console.log('Form data changed:', event.formData);
};

const handleError = (errors: any) => {
console.log('Form errors:', errors);
};

return (
<Box margin={'5rem'}>
<DynamicForm
schema={schema}
uiSchema={uiSchema}
onSubmit={handleSubmit}
onChange={handleChange}
onError={handleError}
widgets={{}}
showErrorList={true}
/>
</Box>
);
};

export default addLearner;
Loading

0 comments on commit 98a6314

Please sign in to comment.