@@ -66,6 +66,109 @@ If you submit the form with an invalid ISBN, you will see:
6666
6767![ Submission error field] ( images/submission-error-field.png )
6868
69+ ### How Server-side Validation Works Under the Hood
70+
71+ When ` fetchHydra ` receives an error response (HTTP status outside the 2xx range), it
72+ [ expands] ( https://www.w3.org/TR/json-ld11-api/#expansion ) the JSON-LD body using the API
73+ documentation context. This means the error object passed to ` getSubmissionErrors ` does not contain
74+ the raw response payload, but an expanded JSON-LD document.
75+
76+ For example, a typical API Platform validation error response:
77+
78+ ``` json
79+ {
80+ "@context" : " /contexts/ConstraintViolationList" ,
81+ "@type" : " ConstraintViolationList" ,
82+ "title" : " An error occurred" ,
83+ "description" : " isbn: This value is neither a valid ISBN-10 nor a valid ISBN-13." ,
84+ "violations" : [
85+ {
86+ "propertyPath" : " isbn" ,
87+ "message" : " This value is neither a valid ISBN-10 nor a valid ISBN-13."
88+ }
89+ ]
90+ }
91+ ```
92+
93+ Gets expanded into a structure like:
94+
95+ ``` json
96+ [
97+ {
98+ "http://www.w3.org/ns/hydra/core#description" : [
99+ {
100+ "@value" : " isbn: This value is neither a valid ISBN-10 nor a valid ISBN-13."
101+ }
102+ ],
103+ "http://www.w3.org/ns/hydra/core#violations" : [
104+ {
105+ "http://www.w3.org/ns/hydra/core#propertyPath" : [{ "@value" : " isbn" }],
106+ "http://www.w3.org/ns/hydra/core#ConstraintViolation/message" : [
107+ {
108+ "@value" : " This value is neither a valid ISBN-10 nor a valid ISBN-13."
109+ }
110+ ]
111+ }
112+ ]
113+ }
114+ ]
115+ ```
116+
117+ This expanded document is what the ` HttpError ` 's ` body ` property contains. The ` getSubmissionErrors `
118+ method of the [ schema analyzer] ( components.md#hydra-schema-analyzer ) handles parsing this expanded
119+ format automatically and maps violations back to field names.
120+
121+ ### Handling Validation Errors Outside React Admin
122+
123+ If you use ` fetchHydra ` in a custom React application (outside of React Admin forms), you need to
124+ handle the expanded JSON-LD error format yourself.
125+
126+ Here is an example of how to extract validation errors from the expanded response:
127+
128+ ``` typescript
129+ import { fetchHydra } from " @api-platform/admin" ;
130+ import type { HttpError } from " react-admin" ;
131+
132+ async function submitData(url : URL , data : object ) {
133+ try {
134+ return await fetchHydra (url , {
135+ method: " POST" ,
136+ body: JSON .stringify (data ),
137+ });
138+ } catch (error ) {
139+ if (error instanceof HttpError && error .status === 422 && error .body ?.[0 ]) {
140+ const content = error .body [0 ];
141+ // Find the violations key (e.g. "http://www.w3.org/ns/hydra/core#violations")
142+ const violationKey = Object .keys (content ).find ((key ) => key .includes (" violations" ));
143+ if (violationKey ) {
144+ const base = violationKey .substring (0 , violationKey .indexOf (" #" ));
145+ const violations = content [violationKey ].map ((violation ) => ({
146+ propertyPath: violation [` ${base }#propertyPath ` ]?.[0 ]?.[" @value" ],
147+ message: (violation [` ${base }#message ` ] ??
148+ violation [` ${base }#ConstraintViolation/message ` ])?.[0 ]?.[" @value" ],
149+ }));
150+ return { violations };
151+ }
152+ }
153+ throw error ;
154+ }
155+ }
156+ ```
157+
158+ Alternatively, you can use the
159+ [ ` jsonld.compact ` ] ( https://github.com/digitalbazaar/jsonld.js#compacting ) method to convert the
160+ expanded response back to a compact form closer to the original payload:
161+
162+ ``` typescript
163+ import jsonld from " jsonld" ;
164+
165+ // Inside your catch block, after getting error.body:
166+ const compacted = await jsonld .compact (error .body , {
167+ " @context" : " http://www.w3.org/ns/hydra/context.jsonld" ,
168+ });
169+ // compacted now has a structure closer to the original API response
170+ ```
171+
69172## Validation With React Admin Inputs
70173
71174If you replace an ` <InputGuesser> ` with a React Admin
0 commit comments