Reusable mui form-dialog with react hook form validation

Viewed 202

I am trying to build a custom material-ui dialog form which uses react-hook-form to validate data.

So, I have two components.

  1. Datatable: It gets data from other components and renders them. Also, attaches methods for different actions: delete, edit or view.

  2. Course: It simply fetches the courses and passes the data to Datatable. It also defines the methods to delete, edit or view.

Passing a function to delete was pretty easy as it only makes an api call. So, I used this pacakge and it worked.

But editing/viewing needs a form which also should validate the data.

I thought to create a function handleView which takes the current row data and passes them to a a function which then returns the component.

This function was being called, but Course component needs to be re-render which is not possible without updating any state.

Also, there is force render but react itself discourages to use.

How can I create this custom reusable material dialog form with react-hook-form validations?

Course.jsx

const Course = () => {
  const { control, handleSubmit } = useForm({
    resolver: yupResolver(schema),
    mode: 'all',
  });
  const confirm = useConfirm();
  const entity = 'courses';
  const { fetch: fetchCourse, response: courses = [] } = useAxios(ApiConfig.COURSE.GET_COURSES);
  const { fetch } = useAxios(COURSE_UPDATE_AXIOS_CONFIG, false);

  const handleDeactivate = (courseId) => {
    confirm({ description: 'Do you want to deactivate course?', confirmationText: 'Yes', title: 'Deactivate Course!' })
      .then(async () => {
        COURSE_UPDATE_AXIOS_CONFIG.url = `${COURSE_UPDATE_AXIOS_CONFIG.url}/${courseId}`;
        COURSE_UPDATE_AXIOS_CONFIG.data = {
          isActive: false,
        };
        console.log(COURSE_UPDATE_AXIOS_CONFIG);
        await fetch();
        await fetchCourse();
      })
      .catch((error) => {
        console.log(error);
      });
  };

  const handleView = (course) => {
    if (course) {
      return (
        <FormDialog>
          <Box component="form" noValidate autoComplete="off" onSubmit={handleSubmit()}>
            <Grid container spacing={4} textAlign="center">
              <Grid item xs={4}>
                <ControlledTextInput name={'name'} control={control} label="Course Name" defaultValue={course.name} />
              </Grid>
              <Grid item xs={4}>
                <ControlledTextInput name={'price'} control={control} label="Course Price" defaultValue={course.price} />
              </Grid>
              <Grid item xs={4}>
                <ControlledTextInput
                  name={'duration'}
                  control={control}
                  label="Course Duration"
                  defaultValue={course.duration}
                />
              </Grid>
            </Grid>
          </Box>
        </FormDialog>
      );
    }
    return course;
  };

  return (
    <Layout>
      <Box padding={2} width="100%">
        <PageTitle pageTitle="Courses" addButton to="/courses/new" />
        {handleView()}
        <Datatable
          entity={entity}
          columns={courseColumns}
          rows={courses}
          deleteRow={handleDeactivate}
          viewRow={handleView}
        />
      </Box>
    </Layout>
  );
};

Datatable.jsx

const Datatable = ({ rows, columns, deleteRow, viewRow }) => {
  const actions = [
    {
      field: 'actions',
      type: 'actions',
      flex: 2,
      headerName: 'Actions',
      getActions: (params) => [
        <GridActionsCellItem
          icon={<Visibility />}
          onClick={() => viewRow(params.row)}
          label="View"
          color="secondary"
          key={params.row.id}
        />,
        <GridActionsCellItem
          icon={<Edit />}
          onClick={() => deleteRow(params.row.id)}
          label="Delete"
          color="warning"
          key={params.row.name}
        />,
        <GridActionsCellItem
          icon={<Delete />}
          onClick={() => deleteRow(params.row.id)}
          label="Delete"
          color="error"
          key={params.row.description}
        />,
      ],
    },
  ];
  return (
    <Box
      sx={{
        boxShadow: '2px 4px 10px 1px rgba(201, 201, 201, 0.47)',
        borderRadius: '10px',
        padding: '20px',
      }}
    >
      <DataGrid
        sx={{
          padding: 2,
        }}
        className="datagrid"
        rows={rows}
        columns={columns.concat(actions)}
        pageSize={15}
        rowsPerPageOptions={[15]}
        autoHeight
        components={{
          Toolbar: GridToolbar,
          LoadingOverlay: LinearProgress,
        }}
        density="comfortable"
        checkboxSelection
        rowHeight={70}
      />
    </Box>
  );
};
0 Answers
Related