Skip to content

Commit

Permalink
Merge pull request #10241 from marmelab/doc/dialog-views/standalaone-…
Browse files Browse the repository at this point in the history
…usage-v2

[Doc] Add "standalaone usage" doc section in dialog views
  • Loading branch information
fzaninotto authored Sep 27, 2024
2 parents 1f73bc8 + 3b55fca commit eda40d9
Show file tree
Hide file tree
Showing 2 changed files with 228 additions and 0 deletions.
114 changes: 114 additions & 0 deletions docs/CreateDialog.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,117 @@ const CompanyShow = () => (
{% endraw %}

In the above example, `<CreateInDialogButton>` is used to create a new employee for the current company. [The `<WithRecord>` component](./WithRecord.md) helps to set the new employee company id by default.

## Standalone Usage

`<CreateDialog>` also offer the ability to work standalone, without using the Router's location.

To allow for standalone usage, they require the following props:

- `isOpen`: a boolean holding the open/close state
- `open`: a function that will be called when a component needs to open the dialog (e.g. a button)
- `close`: a function that will be called when a component needs to close the dialog (e.g. the dialog's close button)

**Tip:** These props are exactly the same as what is stored inside a `FormDialogContext`. This means that you can also rather provide your own `FormDialogContext` with these values, and render your dialog component inside it, to activate standalone mode.

Below is an example of an `<Edit>` page, including a 'create a new customer' button, that opens a fully controlled `<CreateDialog>`.

<video controls autoplay playsinline muted loop>
<source src="https://react-admin-ee.marmelab.com/assets/FullyControlledCreateDialog.mp4" type="video/mp4"/>
Your browser does not support the video tag.
</video>

{% raw %}

```tsx
import React, { useCallback, useState } from 'react';
import {
Button,
Datagrid,
DateField,
DateInput,
Edit,
ReferenceManyField,
required,
SelectField,
SelectInput,
SimpleForm,
TextField,
TextInput,
useRecordContext,
} from 'react-admin';
import { CreateDialog } from '@react-admin/ra-form-layout';

const sexChoices = [
{ id: 'male', name: 'Male' },
{ id: 'female', name: 'Female' },
];

const CustomerForm = (props: any) => (
<SimpleForm defaultValues={{ firstname: 'John', name: 'Doe' }} {...props}>
<TextInput source="first_name" validate={required()} />
<TextInput source="last_name" validate={required()} />
<DateInput source="dob" label="born" validate={required()} />
<SelectInput source="sex" choices={sexChoices} />
</SimpleForm>
);

const EmployerSimpleFormWithFullyControlledDialogs = () => {
const record = useRecordContext();

const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
const openCreateDialog = useCallback(() => {
setIsCreateDialogOpen(true);
}, []);
const closeCreateDialog = useCallback(() => {
setIsCreateDialogOpen(false);
}, []);

return (
<SimpleForm>
<TextInput source="name" validate={required()} />
<TextInput source="address" validate={required()} />
<TextInput source="city" validate={required()} />
<Button
label="Create a new customer"
onClick={() => openCreateDialog()}
size="medium"
variant="contained"
sx={{ mb: 4 }}
/>
<CreateDialog
fullWidth
maxWidth="md"
record={{ employer_id: record?.id }} // pre-populates the employer_id to link the new customer to the current employer
isOpen={isCreateDialogOpen}
open={openCreateDialog}
close={closeCreateDialog}
resource="customers"
>
<CustomerForm />
</CreateDialog>
<ReferenceManyField
label="Customers"
reference="customers"
target="employer_id"
>
<Datagrid>
<TextField source="id" />
<TextField source="first_name" />
<TextField source="last_name" />
<DateField source="dob" label="born" />
<SelectField source="sex" choices={sexChoices} />
</Datagrid>
</ReferenceManyField>
</SimpleForm>
);
};

const EmployerEdit = () => (
<Edit>
<EmployerSimpleFormWithFullyControlledDialogs />
</Edit>
);
```

{% endraw %}
114 changes: 114 additions & 0 deletions docs/EditDialog.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,117 @@ const CompanyShow = () => (
```

Check [the `<EditInDialogButton>` component](./EditInDialogButton.md) for more details.

## Standalone Usage

`<EditDialog>` also offer the ability to work standalone, without using the Router's location.

To allow for standalone usage, they require the following props:

- `isOpen`: a boolean holding the open/close state
- `open`: a function that will be called when a component needs to open the dialog (e.g. a button)
- `close`: a function that will be called when a component needs to close the dialog (e.g. the dialog's close button)

**Tip:** These props are exactly the same as what is stored inside a `FormDialogContext`. This means that you can also rather provide your own `FormDialogContext` with these values, and render your dialog component inside it, to activate standalone mode.

Below is an example of an `<Edit>` page, including a 'create a new customer' button, that opens a fully controlled `<EditDialog>`.

<video controls autoplay playsinline muted loop>
<source src="https://react-admin-ee.marmelab.com/assets/FullyControlledCreateDialog.mp4" type="video/mp4"/>
Your browser does not support the video tag.
</video>

{% raw %}

```tsx
import React, { useCallback, useState } from 'react';
import {
Button,
Datagrid,
DateField,
DateInput,
Edit,
ReferenceManyField,
required,
SelectField,
SelectInput,
SimpleForm,
TextField,
TextInput,
useRecordContext,
} from 'react-admin';
import { EditDialog } from '@react-admin/ra-form-layout';

const sexChoices = [
{ id: 'male', name: 'Male' },
{ id: 'female', name: 'Female' },
];

const CustomerForm = (props: any) => (
<SimpleForm defaultValues={{ firstname: 'John', name: 'Doe' }} {...props}>
<TextInput source="first_name" validate={required()} />
<TextInput source="last_name" validate={required()} />
<DateInput source="dob" label="born" validate={required()} />
<SelectInput source="sex" choices={sexChoices} />
</SimpleForm>
);

const EmployerSimpleFormWithFullyControlledDialogs = () => {
const record = useRecordContext();

const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
const openEditDialog = useCallback(() => {
setIsEditDialogOpen(true);
}, []);
const closeEditDialog = useCallback(() => {
setIsEditDialogOpen(false);
}, []);

return (
<SimpleForm>
<TextInput source="name" validate={required()} />
<TextInput source="address" validate={required()} />
<TextInput source="city" validate={required()} />
<ReferenceManyField
label="Customers"
reference="customers"
target="employer_id"
>
<Datagrid>
<TextField source="id" />
<TextField source="first_name" />
<TextField source="last_name" />
<DateField source="dob" label="born" />
<SelectField source="sex" choices={sexChoices} />
<Button
label="Edit customer"
onClick={() => openEditDialog()}
size="medium"
variant="contained"
sx={{ mb: 4 }}
/>
</Datagrid>
</ReferenceManyField>
<EditDialog
fullWidth
maxWidth="md"
record={{ employer_id: record?.id }} // pre-populates the employer_id to link the new customer to the current employer
isOpen={isEditDialogOpen}
open={openEditDialog}
close={closeEditDialog}
resource="customers"
>
<CustomerForm />
</EditDialog>
</SimpleForm>
);
};

const EmployerEdit = () => (
<Edit>
<EmployerSimpleFormWithFullyControlledDialogs />
</Edit>
);
```

{% endraw %}

0 comments on commit eda40d9

Please sign in to comment.