-
Notifications
You must be signed in to change notification settings - Fork 2
Submitting
The submit
function allows clients to execute an Action
found within an entity received from the server. Because the response to submitting an action may not have Siren content, the result is a Response
object.
import { submit } from '@siren-js/client';
// fields and action objects are from the Modeling page 👉
productCodeField.value = 'ABC123';
quantityField.value = 10;
let response = await submit(addItemAction);
If you can safely assume the server only responds with Siren content, you can easily combine submit
with parse
(see Parsing).
const entity = await submit(addItemAction).then(parse);
Instead of manually populating fields as shown above, you can use the ActionFiller
visitor.
const addItemData = new ActionFiller({
productCode: 'ABC123',
quality: 10
});
await addItemAction.accept(addItemData);
// field's are now populated
response = await submit(addItemAction);
You can provide a baseUrl
in case the action's href
is relative.
response = await submit(addItemAction, {
baseUrl: 'http://api.example.io'
});
Use the requestInit
option to specify the options for the call to fetch
.
response = await submit(addItemAction, {
requestInit: {
headers: {
'Api-Key': 'abcdefghijklmnopqrstuvwxyz'
}
}
});
When submit
is called, each of the action's fields
are validated. By default, all fields pass validation, effectively making validation an opt-in feature. For stricter validation, you can provide a Validator
using the validator
option.
A Validator
is a function that accepts an array of Field
objects and returns a ValidationResult
. When validation passes, return an instance of a PositiveValidationResult
. When validation fails, return an instance of a NegativeValidationResult
.
import { NegativeValidationResult, PositiveValidationResult, Validator } from '@siren-js/client';
function isValid(field: Field): boolean {
if (field.name === 'quantity' && field.value < 1) return false;
if (!field.productCode) return false;
return true;
}
const validator: Validator = (fields) => {
const valid = fields.every(isValid);
if (valid) return new PositiveValidationResult();
else return new NegativeValidationResult();
};
await submit(addItemAction, { validator });
A NegativeValidationResult
signals the submit
function throw a ValidationError
, which wraps the NegativeValidationResult
.
try {
await submit(addItemAction, { validator });
} catch (error) {
if (error instanceof ValidationError) {
console.log(error.result);
}
}
You'll likely need more info than the NegativeValidationResult
implementation gives you. Simply extend NegativeValidationResult
with the additional fields you need. As long as you return a subclass of NegativeValidationResult
, submit
will interpret the result as failed validation.
class GoofedValidation extends NegativeValidationResult {
constructor(readonly invalidFields: Field[]) {
super();
}
}
const informativeValidator: Validator = (fields) => {
const invalidFields = fields.filter((field) => !isValid(field));
if (invalidFields.length > 0) return new GoofedValidation(invalidFields);
else return new PositiveValidationResult();
};
try {
await submit(addItemAction, { validator: informativeValidator });
} catch (error) {
if (error instanceof ValidationError && error.result instanceof GoofedValidation) {
console.log('Fields failing validation:');
error.result.invalidFields.forEach((field) => console.log(field.name));
}
}
After the action's fields
are validated, they are serialized. By default, fields are serialized using the defaultSerializer
. To customize field serialization, provide a Serializer
using the serializer
option.
// TODO