Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Submit

Bind value-bearing controls to the model; submission is a separate action. BeverlyPlugin includes FormPlugin, which watches the generated submit button and emits FormSubmitted with the owning form entity and a FormRequest. The app owns network transport and response handling.

Methods and Encodings

Use the constructor matching the requested HTTP verb:

ConstructorRequest methodFields
Form::get(url)GETURL query string
Form::post(url)POSTRequest body
Form::put(url)PUTRequest body
Form::patch(url)PATCHRequest body

GET fields are URL-encoded and appended to existing query parameters before any fragment. POST, PUT, and PATCH use FormEncoding::UrlEncoded by default; .encoding(FormEncoding::Json) sends a JSON object instead. A field name can occur more than once in URL-encoded data.

#![allow(unused)]
fn main() {
let create = Form::post("https://example.test/items")
    .encoding(FormEncoding::Json)
    .field("title", "Release notes")
    .build_request();

let update = Form::put("https://example.test/items/42")
    .field("title", "Revised release notes")
    .build_request();

let partial_update = Form::patch("https://example.test/items/42")
    .field("published", "true")
    .build_request();
}

Form::field(...) and Form::fields(...) add fixed string values. Named supported descendant controls add their current values. Disabled controls and unchecked checkbox/toggle controls are omitted. The string-valued request API does not upload files.

Handling Submission

The generated submit control gathers values and emits a message; it does not perform a request:

#![allow(unused)]
fn main() {
use bevy::prelude::*;
use beverly::prelude::*;

fn search_form() -> UiElement {
    UiElement::form(Form::get("https://example.test/search"))
        .children([
            UiElement::input("Search terms")
                .label("Search terms")
                .name("q"),
        ])
}

fn handle_form_submit(mut submitted: MessageReader<FormSubmitted>) {
    for message in submitted.read() {
        let request = &message.request;
        info!(form = ?message.form, method = ?request.method, url = %request.request_url());
    }
}
}

For POST/PUT/PATCH, request_url() returns the action URL; values remain in request.fields for the selected body encoding. The default Bevy update path never performs blocking network I/O. With the optional http_form Cargo feature, FormRequest::send() and Form::submit() are blocking reqwest conveniences; call them from an app-owned worker/task, not from a Bevy system.

A custom submit button must carry the FormSubmitButton marker from beverly::components::form; the default generated button already has it. Nested forms are not included in an outer form’s field collection.

Pending and Errors

The application controls request state. Add .submitting(|| ...) and .success(|| ...) callbacks to the form or submit control, then set FormStatusState after beginning and completing the operation. These callbacks only render supplementary content; they do not observe requests or disable controls automatically. Use .disabled(true) when that is the intended policy.

Global request failures are also app-owned. Set BindingErrorState on the Form entity to render its .error(...) callback. Field errors are not aggregated into the Form automatically. See Form State and Error Callbacks.