Skip to content

Commit 98a06f9

Browse files
authored
Server-side validation documentation (api-platform#1265)
1 parent d4c7049 commit 98a06f9

File tree

6 files changed

+118
-47
lines changed

6 files changed

+118
-47
lines changed

admin/components.md

Lines changed: 48 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,30 @@
44

55
### AdminGuesser
66

7-
`<AdminGuesser>` creates a complete Admin Context and Interface, rendering automatically an [`<AdminUI>` component](https://marmelab.com/react-admin/Admin.html#unplugging-the-admin-using-admincontext-and-adminui) for resources exposed by a web API documented with any format supported by `@api-platform/api-doc-parser` (for Hydra documented APIs,
8-
use the [`<HydraAdmin>`component](admin/components.md#hydraadmin) instead). It also creates a [`schemaAnalyzer`](admin/components.md#schemaAnalyzer) context, where the schemaAnalyzer service (for getting information about the provided API documentation) is stored.
7+
`<AdminGuesser>` renders automatically an [<Admin> component](https://marmelab.com/react-admin/Admin.html) for resources exposed by a web API documented with any format supported by `@api-platform/api-doc-parser` (for Hydra documented APIs,
8+
use the [<HydraAdmin> component](components.md#hydraadmin) instead).
9+
It also creates a [schema analyzer](components.md#schemaanalyzer) context, where the `schemaAnalyzer` service (for getting information about the provided API documentation) is stored.
910

10-
The `<AdminGuesser>` renders all exposed resources by default, but you can choose what resource you want to render by passing [`<ResourceGuesser>` components](admin/components/#resourceguesser) as children.
11+
`<AdminGuesser>` renders all exposed resources by default, but you can choose what resource you want to render by passing [<ResourceGuesser> components](components.md#resourceguesser) as children.
1112
Deprecated resources are hidden by default, but you can add them back using an explicit `<ResourceGuesser>` component.
1213

1314
```javascript
14-
//App.js
15-
import { AdminGuesser, ResourceGuesser } from '@api-platform/admin';
15+
// App.js
16+
import { AdminGuesser, ResourceGuesser } from "@api-platform/admin";
1617

1718
const App = () => (
1819
<AdminGuesser
1920
entrypoint={entrypoint}
2021
dataProvider={dataProvider}
2122
authProvider={authProvider}>
22-
<ResourceGuesser
23-
name"books"
24-
list={BooksList}
25-
show={BooksShow}
26-
edit={BooksEdit}
27-
create={BooksCreate} />
28-
<ResourceGuesser name"authors" />
29-
</AdminGuesser>
23+
<ResourceGuesser
24+
name"books"
25+
list={BooksList}
26+
show={BooksShow}
27+
edit={BooksEdit}
28+
create={BooksCreate} />
29+
<ResourceGuesser name"authors" />
30+
</AdminGuesser>
3031
)
3132

3233
export default App;
@@ -44,12 +45,12 @@ export default App;
4445

4546
### ResourceGuesser
4647

47-
Based on React-Admin's [`<Resource>` component](https://marmelab.com/react-admin/Resource.html), the ResourceGuesser provides default props [`<CreateGuesser>`](admin/components.md#createguesser), [`<ListGuesser>`](admin/components.md#listguesser), [`<EditGuesser>`](admin/components.md#editguesser) and [`<ShowGuesser>`](admin/components.md#showguesser).
48-
Otherwise you can pass it your own CRUD components using `create`, `list`, `edit`, `show` props.
48+
Based on React Admin [<Resource> component](https://marmelab.com/react-admin/Resource.html), `ResourceGuesser` provides default props [<CreateGuesser>](components.md#createguesser), [<ListGuesser>](components.md#listguesser), [<EditGuesser>](components.md#editguesser) and [<ShowGuesser>](components.md#showguesser).
49+
Otherwise, you can pass it your own CRUD components using `create`, `list`, `edit`, `show` props.
4950

5051
```javascript
5152
// App.js
52-
import { AdminGuesser, ResourceGuesser } from '@api-platform/admin';
53+
import { AdminGuesser, ResourceGuesser } from "@api-platform/admin";
5354

5455
const App = () => (
5556
<AdminGuesser
@@ -76,23 +77,23 @@ export default App;
7677
|------|--------|-------|----------|--------------------------|
7778
| name | string | - | yes | endpoint of the resource |
7879

79-
You can also use props accepted by React-Admin's [`<Resource>` component](https://marmelab.com/react-admin/Resource.html). For example, the props `list`, `show`, `create` & `edit`.
80+
You can also use props accepted by React Admin [<Resource> component](https://marmelab.com/react-admin/Resource.html). For example, the props `list`, `show`, `create` or `edit`.
8081

8182
## Page Components
8283

8384
### ListGuesser
8485

85-
Based on React-Admin's [`<List>`](https://marmelab.com/react-admin/List.html), ListGuesser displays a list of resources in a [`<Datagrid>`](https://marmelab.com/react-admin/List.html#the-datagrid-component), according to children passed to it (usually [`<FieldGuesser>`](admin/components/#fieldguesser) or any [`field` component](https://marmelab.com/react-admin/Fields.html#basic-fields)
86-
available in React-Admin).
86+
Based on React Admin [<List>](https://marmelab.com/react-admin/List.html), ListGuesser displays a list of resources in a [<Datagrid>](https://marmelab.com/react-admin/List.html#the-datagrid-component), according to children passed to it (usually [<FieldGuesser>](components.md#fieldguesser) or any [field component](https://marmelab.com/react-admin/Fields.html#basic-fields)
87+
available in React Admin).
8788

8889
Use `hasShow` and `hasEdit` props if you want to display `show` and `edit` buttons (both set to `true` by default).
8990

90-
By default, `<ListGuesser>` comes with [`<Pagination>`](admin/components.md#pagination).
91+
By default, `<ListGuesser>` comes with [<Pagination>](components.md#pagination).
9192

9293
```javascript
9394
// BooksList.js
94-
import { FieldGuesser, ListGuesser } from '@api-platform/admin';
95-
import { ReferenceField, TextField } from 'react-admin';
95+
import { FieldGuesser, ListGuesser } from "@api-platform/admin";
96+
import { ReferenceField, TextField } from "react-admin";
9697

9798
export const BooksList = props => (
9899
<ListGuesser {...props}>
@@ -113,16 +114,16 @@ export const BooksList = props => (
113114
| resource | string | - | yes | endpoint of the resource |
114115
| filters | element | - | no | filters that can be applied to the list |
115116

116-
You can also use props accepted by React-Admin's [`<List>`](https://marmelab.com/react-admin/List.html).
117+
You can also use props accepted by React Admin [<List>](https://marmelab.com/react-admin/List.html).
117118

118119
### CreateGuesser
119120

120-
Displays a creation page for a single item. Uses React-Admin's [`<Create>`](https://marmelab.com/react-admin/Edit.html) and [`<SimpleForm>`](https://marmelab.com/react-admin/CreateEdit.html#the-simpleform-component).
121-
For simple inputs, you can pass as children API Platform Admin's [`<InputGuesser>`](admin/components.md#inputguesser), or any React-Admin's [`Input components`](https://marmelab.com/react-admin/Inputs.html#input-components) for more complex inputs.
121+
Displays a creation page for a single item. Uses React Admin [<Create>](https://marmelab.com/react-admin/CreateEdit.html) and [<SimpleForm>](https://marmelab.com/react-admin/CreateEdit.html#the-simpleform-component) components.
122+
For simple inputs, you can pass as children API Platform Admin [<InputGuesser>](components.md#inputguesser), or any React Admin [Input components](https://marmelab.com/react-admin/Inputs.html#input-components) for more complex inputs.
122123

123124
```javascript
124125
// BooksCreate.js
125-
import { CreateGuesser, InputGuesser } from '@api-platform/admin';
126+
import { CreateGuesser, InputGuesser } from "@api-platform/admin";
126127

127128
export const BooksCreate = props => (
128129
<CreateGuesser {...props}>
@@ -137,22 +138,21 @@ export const BooksCreate = props => (
137138

138139
#### CreateGuesser Props
139140

140-
| Name | Type | Value | required | Description |
141141
| Name | Type | Value | required | Description |
142142
|----------|------------------|-------|----------|--------------------------|
143143
| children | node or function | - | no | - |
144144
| resource | string | - | yes | endpoint of the resource |
145145

146-
You can also use props accepted by React-Admin's [`<Create>`](https://marmelab.com/react-admin/Edit.html).
146+
You can also use props accepted by React Admin [<Create>](https://marmelab.com/react-admin/CreateEdit.html).
147147

148148
### EditGuesser
149149

150-
Displays an edition page for a single item. Uses React-Admin's [`<Edit>`](https://marmelab.com/react-admin/Edit.html) and [`<SimpleForm>`](https://marmelab.com/react-admin/CreateEdit.html#the-simpleform-component) components.
151-
For simple inputs, you can use API Platform Admin's [`<InputGuesser>`](admin/components.md#inputguesser), or any React-Admin's [`Input components`](https://marmelab.com/react-admin/Inputs.html#input-components) for more complex inputs.
150+
Displays an edition page for a single item. Uses React Admin [<Edit>](https://marmelab.com/react-admin/CreateEdit.html) and [<SimpleForm>](https://marmelab.com/react-admin/CreateEdit.html#the-simpleform-component) components.
151+
For simple inputs, you can use API Platform Admin [<InputGuesser>](components.md#inputguesser), or any React Admin [Input components](https://marmelab.com/react-admin/Inputs.html#input-components) for more complex inputs.
152152

153153
```javascript
154154
// BooksEdit.js
155-
import { EditGuesser, InputGuesser } from '@api-platform/admin';
155+
import { EditGuesser, InputGuesser } from "@api-platform/admin";
156156

157157
export const BooksEdit = props => (
158158
<EditGuesser {...props}>
@@ -172,15 +172,15 @@ export const BooksEdit = props => (
172172
| children | node or function | - | no | - |
173173
| resource | string | - | yes | endpoint of the resource |
174174

175-
You can also use props accepted by React-Admin's [`<Edit>`](https://marmelab.com/react-admin/Edit.html).
175+
You can also use props accepted by React Admin [<Edit>](https://marmelab.com/react-admin/CreateEdit.html).
176176

177177
### ShowGuesser
178178

179-
Displays a detailed page for one item. Based on React-Admin's [`<Show>` component](https://marmelab.com/react-admin/Show.html). You can pass [`<FieldGuesser>`](admin/components.md#fieldguesser) as children for simple fields, or use any of React-Admin's [`Basic Fields`](https://marmelab.com/react-admin/Fields.html#basic-fields) for more complex fields.
179+
Displays a detailed page for one item. Based on React Admin [<Show> component](https://marmelab.com/react-admin/Show.html). You can pass [<FieldGuesser>](components.md#fieldguesser) as children for simple fields, or use any of React Admin [basic fields](https://marmelab.com/react-admin/Fields.html#basic-fields) for more complex fields.
180180

181181
```javascript
182182
// BooksShow.js
183-
import { FieldGuesser, ShowGuesser } from '@api-platform/admin';
183+
import { FieldGuesser, ShowGuesser } from "@api-platform/admin";
184184

185185
export const BooksShow = props => (
186186
<ShowGuesser {...props}>
@@ -200,17 +200,17 @@ export const BooksShow = props => (
200200
| children | node or function | - | no | - |
201201
| resource | string | - | yes | endpoint of the resource |
202202

203-
You can also use props accepted by React-Admin's [`<Show>` component](https://marmelab.com/react-admin/Show.html).
203+
You can also use props accepted by React Admin [<Show> component](https://marmelab.com/react-admin/Show.html).
204204

205205
## Hydra
206206

207207
### HydraAdmin
208208

209-
Creates a complete Admin Context and Interface, as [`<AdminGuesser>`](/admin/components.md#adminguesser), but configured specially for [Hydra](https://www.hydra-cg.com/). If you want to use other formats (see supported formats: `@api-platform/api-doc-parser`) use the [`<AdminGuesser>`](admin/components.md#adminguesser) instead.
209+
Creates a complete Admin, as [`<AdminGuesser>`](components.md#adminguesser), but configured specially for [Hydra](https://www.hydra-cg.com/). If you want to use other formats (see supported formats: `@api-platform/api-doc-parser`) use [<AdminGuesser>](components.md#adminguesser) instead.
210210

211211
```javascript
212212
// App.js
213-
import { HydraAdmin, ResourceGuesser } from '@api-platform/admin';
213+
import { HydraAdmin, ResourceGuesser } from "@api-platform/admin";
214214

215215
const App = () => (
216216
<HydraAdmin
@@ -232,28 +232,30 @@ export default App;
232232
|------------|--------|-------|----------|-----------------------|
233233
| entrypoint | string | - | yes | entrypoint of the API |
234234

235-
### dataProvider
235+
### Data Provider
236236

237-
Based on React-Admin's `Create`, `Delete`, `getList`, `getManyReference`, `GetOne`, `Update` methods, the `dataProvider` is used by API Platform Admin to communicate with the API. In addition, the specific `introspect` method parses your API documentation.
238-
Note that the `dataProvider` can be overrided to fit your API needs.
237+
Based on React Admin `create`, `delete`, `getList`, `getManyReference`, `getOne`, `update` methods, the `dataProvider` is used by API Platform Admin to communicate with the API. In addition, the specific `introspect` method parses your API documentation.
238+
Note that the `dataProvider` can be overridden to fit your API needs.
239239

240-
### schemaAnalyzer
240+
### Schema Analyzer
241241

242242
Analyses your resources and retrieves their types according to the [Schema.org](https://schema.org) vocabulary.
243243

244244
## Other Components
245245

246246
### Pagination
247247

248-
Set by default in the [`<ListGuesser/>` component](/admin/components.md#listguesser), the `<Pagination/> component` uses React-Admin's [`<Pagination>` component](https://marmelab.com/react-admin/List.html#pagination). By default, it renders 30 items per page and displays a navigation UI. If you want to change the number of items per page or disable the pagination, see the [`Pagination` documentation](https://api-platform.com/docs/core/pagination/#pagination).
248+
Set by default in the [<ListGuesser> component](components.md#listguesser), the `Pagination` component uses React Admin [<Pagination> component](https://marmelab.com/react-admin/List.html#pagination).
249+
By default, it renders 30 items per page and displays a navigation UI. If you want to change the number of items per page or disable the pagination, see the [Pagination documentation](../core/pagination.md).
250+
It is also capable to handle partial pagination.
249251

250252
### FieldGuesser
251253

252-
Renders fields according to their types, using [`schemaAnalyzer`](/admin/components.md#schemaanalyzer). Based on React-Admin's [`<ReferenceField>` component](https://marmelab.com/react-admin/Fields.html#referencefield).
254+
Renders fields according to their types, using the [schema analyzer](components.md#schemaanalyzer). Based on React Admin [field components](https://marmelab.com/react-admin/Fields.html).
253255

254256
```javascript
255257
// BooksShow.js
256-
import { FieldGuesser, ShowGuesser } from '@api-platform/admin';
258+
import { FieldGuesser, ShowGuesser } from "@api-platform/admin";
257259

258260
export const BooksShow = props => (
259261
<ShowGuesser {...props}>
@@ -272,11 +274,11 @@ export const BooksShow = props => (
272274
|--------|--------|-------|----------|--------------------------|
273275
| source | string | - | yes | endpoint of the resource |
274276

275-
You can also use props accepted by React-Admin's [`Basic Fields`](https://marmelab.com/react-admin/Fields.html#basic-fields).
277+
You can also use props accepted by React Admin [basic fields](https://marmelab.com/react-admin/Fields.html#basic-fields).
276278

277279
### InputGuesser
278280

279-
Uses React-Admin's [`<ReferenceInput>`](https://marmelab.com/react-admin/Inputs.html#referenceinput) to generate inputs according to your API documentation (e.g. number HTML input for numbers, checkbox for booleans, selectbox for relationships...)
281+
Uses React Admin [input components](https://marmelab.com/react-admin/Inputs.html) to generate inputs according to your API documentation (e.g. number HTML input for numbers, checkbox for booleans, selectbox for relationships...).
280282

281283
#### InputGuesser Props
282284

admin/images/required-field.png

2.08 KB
Loading
5.74 KB
Loading

admin/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ according to the API-first paradigm.
1414
API Platform Admin parses the API documentation then uses the awesome [React Admin](https://marmelab.com/react-admin/)
1515
library to expose a nice, responsive, management interface (Create-Retrieve-Update-Delete) for all documented resource types.
1616

17-
You can **customize everything** by using provided React Admin and [Material UI](https://material-ui.com/) components, or by writing your custom [React](https://reactjs.org/) components.
17+
You can **customize everything** by using provided React Admin and [Material UI](https://material-ui.com/) components, or by writing your custom [React](https://reactjs.org/) components.
1818

1919
## Features
2020

admin/validation.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Validation
2+
3+
API Platform Admin manages automatically two types of validation: client-side validation and server-side (or submission) validation.
4+
5+
## Client-side Validation
6+
7+
If the API documentation indicates that a field is mandatory,
8+
API Platform Admin will automatically add a [required client-side validation](https://marmelab.com/react-admin/CreateEdit.html#per-input-validation-built-in-field-validators).
9+
10+
For instance, with API Platform Core as backend, if you write the following:
11+
12+
```php
13+
<?php
14+
// api/src/Entity/Book.php
15+
16+
use ApiPlatform\Core\Annotation\ApiResource;
17+
use Symfony\Component\Validator\Constraints as Assert;
18+
19+
/**
20+
* @ApiResource
21+
*/
22+
class Book
23+
{
24+
/**
25+
* @Assert\NotBlank
26+
*/
27+
public ?string $title = null;
28+
}
29+
```
30+
31+
If you create a new book and touch the "Title" field without typing, you will see:
32+
33+
![Required title field](images/required-field.png)
34+
35+
## Server-side Validation
36+
37+
When the form is submitted and if submission errors are received,
38+
API Platform Admin will automatically show the errors for the corresponding fields.
39+
40+
To do so, it uses the [submission validation](https://marmelab.com/react-admin/CreateEdit.html#submission-validation) feature of React Admin,
41+
and the mapping between the response and the fields is done by the [schema analyzer](components.md#schemaanalyzer) with its method `getSubmissionErrors`.
42+
43+
API Platform Core is supported by default, but if you use another backend, you will need to override the `getSubmissionErrors` method.
44+
45+
For example if you have this code:
46+
47+
```php
48+
<?php
49+
// api/src/Entity/Book.php
50+
51+
use ApiPlatform\Core\Annotation\ApiResource;
52+
use Symfony\Component\Validator\Constraints as Assert;
53+
54+
/**
55+
* @ApiResource
56+
*/
57+
class Book
58+
{
59+
/**
60+
* @Assert\Isbn
61+
*/
62+
public ?string $isbn = null;
63+
}
64+
```
65+
66+
If you submit the form with an invalid ISBN, you will see:
67+
68+
![Submission error field](images/submission-error-field.png)

outline.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ chapters:
6464
- getting-started
6565
- handling-relations
6666
- schema.org
67+
- validation
6768
- authentication-support
6869
- file-upload
6970
- performance

0 commit comments

Comments
 (0)