Submit crop data with standard HTML forms using ElementInternals.
<crop-image> is a form-associated custom element. When you set the name attribute, it participates in form submission just like a native <input>.
The form value is automatically set to the RIAPI querystring of the current crop selection. It updates on every crop-change and crop-commit event.
<form action="/api/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="image" accept="image/*">
<crop-image
name="crop"
src="/preview.jpg"
aspect-ratio="16/9"
adapter="imageflow"
></crop-image>
<button type="submit">Upload & Crop</button>
</form>
When submitted, the form data includes:
image: [file data]
crop: ?crop=0.1,0.1,0.9,0.9&cropxunits=1&cropyunits=1
const form = document.querySelector('form');
form.addEventListener('submit', (e) => {
e.preventDefault();
const data = new FormData(form);
const cropQs = data.get('crop');
console.log(cropQs);
// "?crop=0.1,0.1,0.9,0.9&cropxunits=1&cropyunits=1"
});
The element exposes standard form-associated properties:
| Property | Type | Description |
|---|---|---|
.form | HTMLFormElement | null | The containing form element |
.name | string | null | The form field name (from the name attribute) |
.type | 'crop-image' | The element's form type identifier |
.validity | ValidityState | Validity state (always valid) |
.validationMessage | string | Validation message (always empty) |
If you prefer a hidden input (for broader browser support or framework compatibility), mirror the querystring manually:
<form action="/api/crop" method="POST">
<input type="hidden" name="crop" id="crop-input">
<crop-image
src="/photo.jpg"
adapter="imageflow"
></crop-image>
<button type="submit">Save</button>
</form>
<script type="module">
import '@imazen/crop-image';
const cropper = document.querySelector('crop-image');
const input = document.getElementById('crop-input');
cropper.addEventListener('crop-commit', (e) => {
input.value = e.detail.riapi.querystring;
});
</script>
Use different name attributes for multiple crop elements in one form:
<form>
<crop-image name="thumbnail" src="/photo.jpg" aspect-ratio="1/1"></crop-image>
<crop-image name="banner" src="/photo.jpg" aspect-ratio="16/9"></crop-image>
<button type="submit">Save Crops</button>
</form>
Form data will include both:
thumbnail: ?crop=0.2,0.1,0.8,0.7&cropxunits=1&cropyunits=1
banner: ?crop=0.0,0.2,1.0,0.8&cropxunits=1&cropyunits=1
The RIAPI querystring format is natively understood by:
crop, cropxunits, cropyunits parameters are standardFor the generic adapter, the crop coordinates are 0..1 fractions. To convert to pixels server-side, multiply by the source image dimensions:
# Python example
crop_str = request.form['crop'] # "0.1,0.2,0.9,0.8"
x1, y1, x2, y2 = [float(v) for v in crop_str.split(',')]
pixel_x1 = int(x1 * source_width)
pixel_y1 = int(y1 * source_height)
pixel_x2 = int(x2 * source_width)
pixel_y2 = int(y2 * source_height)
Browser support: ElementInternals and form-associated custom elements are supported in all modern browsers (Chrome 77+, Firefox 98+, Safari 16.4+). For older browsers, use the hidden input approach.