Developer Docs - Mobile Docs - Forms and Values

On the web, a form posts its inputs because each one has a name. Mobile does the same thing, using HelixForm as the scope and Hx.Id as the name.

HelixForm

HelixForm is the mobile analog of web Helix's lava-form. It needs no prefix, and it is a VerticalStackLayout, so it stacks its children vertically and takes Spacing, Padding, and the rest.



    

    
        
    

    
        
        
    

    

The form carries the verb

Hx.Post goes on the HelixForm, not on the submit button. Any Button inside the form with no verb of its own and no Command is a submit button. That is the default, so the Submit button above needs no Helix attributes at all.

To opt a button out, give it any one of these:

Tapping the form's background does not submit it. Forms are excluded from natural tap wiring. If you genuinely want a tappable form surface, say so explicitly with Hx.Trigger="tapped".

Form behavior details

Inline validation, and why this matters

Look again at the email field above. Hx.Target="this" Hx.Swap="outer" sits on the FieldContainer, not on the TextBox. The TextBox inherits both, and this resolves to the element that declared it, which is the container. So every time the person leaves that field, the response replaces that one field's container in place.

Which means your endpoint has to return the field, not just a message. outer destroys the container it replaces, so whatever comes back is the field from then on. Return the whole container:


    
    {% if isTaken %}
    

Every attribute reappears, and each one breaks something different if you leave it out:

That is the standing cost of outer: it is the only swap that removes the element carrying your attributes, so the response has to re-declare them. See Requests and Targeting.

This is a direct port of HTMX's canonical inline validation pattern, and it is the clearest reason to understand Inheritance.

Automatic value inclusion

What gets included

A control with no name is never included. That is the mobile stand-in for HTML's "no name, no submit."

Naming a control: prefer Hx.Id

Either Hx.Id or x:Name gives a control the name its value is submitted under, and Helix checks Hx.Id first, so it wins if a control carries both. Prefer Hx.Id: it is the name Helix actually looks for, and it says plainly that the name exists for Helix rather than for something else. x:Name works only because MAUI mirrors it onto a property Helix falls back to.

The one place you still need x:Name is {x:Reference ...}, which resolves XAML names and cannot see an Hx.Id. If you need to both reference a control in a binding and submit its value, give it both.

How it travels

What the app can read

That last row is narrower than it looks. A Slider, a Stepper, a Label, or a layout contributes nothing, because Helix has no value property to read from it.

Prefer the Rock: fields inside a form anyway. They carry the label, IsRequired and the validation behavior, and they usually report the value you actually want: Rock:Picker submits its SelectedValue, where a bare MAUI Picker submits the selected item's display text. Here is what each one contributes:

Your endpoint must treat Form and QueryString as untrusted no matter what the app "should" have sent. See Security.

Hx.Include

Use it for values automatic inclusion cannot reach: something computed, or a control outside the initiator's scope.




This is the exception to preferring Hx.Id. {x:Reference} resolves XAML names, so the control it points at needs x:Name; an Hx.Id alone is invisible to it.

Hx.Params





    

Because it inherits, Hx.Params="none" on a HelixForm excludes every field in that form. Occasionally that is what you want. Usually it is a mistake.

Validation

Helix reuses the validation the app already has: IsRequired, ValidationExpression, and ValidationExpressionMessage on Rock fields, plus the Validator control.

There is no opt-in flag. When a validator is in play, it gates the request.

Inside a form

A form submission validates the form's visible fields automatically, before sending.

Validation runs only for a form submission. Inline field triggers inside the form, and buttons with their own verbs, are not submissions and skip it.

Outside a form: Hx.Validator


    
        email
    


Failure shows the validator's messages and aborts. No request is sent.