【问题标题】:How to add a form input on a Dialog from Show view with React Admin?如何使用 React Admin 在显示视图中的对话框上添加表单输入?
【发布时间】:2020-12-20 19:51:00
【问题描述】:

总结

我想在记录显示视图上添加一个快速操作按钮,该按钮将显示一个带有表单字段的对话框。

提交表单时,我希望提供的数据用于发送带有表单字段数据和一些选项的更新操作。

我知道如何创建将在数据提供者上调度更新操作的操作按钮,但我不知道如何处理对话框上的表单。

尝试(和失败)

所以我首先创建了一个按钮,该按钮显示一个带有TextInput(来自react-admin)的对话框:

const ValidateButton: FC<ButtonProps> = ({ record }) => {
  const [open, setOpen] = useState<boolean>(false);

  const handleInit = () => {
    setOpen(true)
  }

  const handleCancel = () => {
    setOpen(false);
  }

  const handleSubmit = () => {
    setOpen(false);
  }

  return (
    <>
      <Button
        label="Validate"
        onClick={handleInit}
      >
        <ValidateIcon />
      </Button>
      <Dialog
        open={open}
      >
        <DialogTitle>Validate</DialogTitle>
        <DialogContent>
          <TextInput
            source="comment"
            label="Validation comment"
          />
        </DialogContent>
        <DialogActions>
          <Button
            label="Cancel"
            onClick={handleCancel}
          />
          <Button
            label="Validate"
            onClick={handleSubmit}
          />
        </DialogActions>
      </Dialog>
    </>
  );
}

这给了我以下错误:

Error: useField must be used inside of a <Form> component

嗯。很清楚。所以我尝试将它包装在 SimpleForm 组件上:

<DialogContent>
  <SimpleForm
    form={createForm({ onSubmit: handleSubmit })}
    resource="rides"
    record={record}
  >
    <TextInput
      source="comment"
      label="Validation comment"
    />
  </SimpleForm>
</DialogContent>

然后我得到:

TypeError: can't access property "save", context is undefined
useSaveContext
node_modules/ra-core/esm/controller/details/SaveContext.js:23

  20 |  */
  21 | export var useSaveContext = function (props) {
  22 |     var context = useContext(SaveContext);
> 23 |     if (!context.save || !context.setOnFailure) {
  24 |         /**
  25 |          * The element isn't inside a <SaveContextProvider>
  26 |          * To avoid breakage in that case, fallback to props

ValidateButton 在显示视图工具栏上实现:

const RideShowActions: FC<ShowActionsProps> = ({ basePath, data }) => {
  if (!data) {
    return null;
  }

  return (
    <TopToolbar>
      <ValidateButton />
      {[
        'created',
        'validated',
        'confirmed',
      ].includes(data?.status) && <CancelButton basePath={basePath} record={data} />}
      <EditButton basePath={basePath} record={data} />
    </TopToolbar>
  );
};

export const RideShow: FC<ShowProps> = (props) => (
  <Show
    title={<RideTitle />}
    actions={<RideShowActions />}
    {...props}
  >
    <SimpleShowLayout>
      // Show classic stuff.
    </SimpleShowLayout>
  </Show>
);

问题

我想最后一个错误是因为SimpleForm 需要放在&lt;Edit&gt; 或类似的地方。

我的目标只是让输入具有与对话框上的编辑表单相同的功能和 UX/UI 设计,并执行自定义操作。

我错过了什么?我怎样才能做到这一点?

注意:我尝试直接使用@material-ui/coreTextField 组件。它可以工作,但我失去了所有对我有用的 react-admin 功能,比如ReferenceInput

【问题讨论】:

    标签: javascript reactjs typescript react-admin


    【解决方案1】:

    我终于找到了解决方案,创建了一个自定义的DialogForm 组件,结合了表单本身和操作按钮等常见逻辑:

    import { FC, MouseEventHandler } from 'react';
    import { Button } from 'react-admin';
    import { Dialog, DialogProps, DialogTitle, DialogContent, DialogActions } from '@material-ui/core'
    import { Form } from 'react-final-form';
    import { Config } from 'final-form';
    
    export interface DialogFormProps {
      open: DialogProps['open'],
      loading?: boolean;
      onSubmit: Config['onSubmit'],
      onCancel: MouseEventHandler,
      title?: string,
      submitLabel?: string;
      cancelLabel?: string;
    }
    
    export const DialogForm: FC<DialogFormProps> = ({
      open,
      loading,
      onSubmit,
      onCancel,
      title,
      cancelLabel,
      submitLabel,
      children,
    }) => {
      return (
        <Dialog
          open={open}
        >
            <Form
              onSubmit={onSubmit}
              render={({handleSubmit}) => (
                <form onSubmit={handleSubmit}>
                  {title && (
                    <DialogTitle>
                      {title}
                    </DialogTitle>
                  )}
                  <DialogContent>
                    {children}
                  </DialogContent>
                  <DialogActions>
                    <Button
                      label={cancelLabel || 'Cancel'}
                      onClick={onCancel}
                      disabled={loading}
                    />
                    <Button
                      label={submitLabel || 'Validate'}
                      type="submit"
                      disabled={loading}
                    />
                  </DialogActions>
                </form>
              )}
            />
    
        </Dialog>
      )
    };
    
    export default null;
    

    您可以复制/粘贴上面的示例,使其开箱即用。

    这是一个带有按钮的实现示例:

    const ValidateButton: FC<ButtonProps> = ({ record }) => {
      const [open, setOpen] = useState<boolean>(false);
    (undefined);
      const [mutate, { loading }] = useMutation();
      const notify = useNotify();
      const refresh = useRefresh();
    
      const handleInit = () => {
        setOpen(true)
      }
    
      const handleCancel = () => {
        setOpen(false);
      }
    
      const handleSubmit: DialogFormProps['onSubmit'] = (values) => {
        console.log(values);
        mutate(
          // Your mutation logic.
        );
      }
    
      return (
        <>
          <Button
            label="Validate"
            onClick={handleInit}
          >
            <ValidateIcon />
          </Button>
          <DialogForm
            open={open}
            loading={loading}
            onSubmit={handleSubmit}
            onCancel={handleCancel}
            title="Validate that thing"
            submitLabel="Let's go!"
          >
            <DialogContentText>
              Some text.
            </DialogContentText>
            <ReferenceInput
              source="referenceId"
              label="Reference"
              reference="service"
              filter={{ userId: record?.customerId }}
            >
              <SelectInput
                optionText="name"
                resettable
                fullWidth
              />
            </ReferenceInput>
          </DialogForm>
        </>
      );
    }
    

    希望它会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-13
      • 2020-05-01
      • 1970-01-01
      • 2013-08-05
      • 2012-09-10
      • 1970-01-01
      • 2022-10-15
      相关资源
      最近更新 更多