Summary#
onEnter binds an action to the Enter key, so a keyboard user can submit a field without reaching for the
mouse:
component SignInCard() {
string email = "";
string password = "";
action SignIn() { Session.SignIn(Login(email, password)); }
render {
Stack(gap: 3) {
Input(value: email, onEnter: SignIn);
Input(value: password, type: "password", onEnter: SignIn);
Pressable(onClick: SignIn) { Text("Sign in"); }
}
}
}Enter in either field runs SignIn, just as clicking the button does.
That fragment shows only the binding. A working sign-in also needs the Login function marked [AuthMethod]
(so a signed-out visitor may call it at all) and wired into app.AuthBootstrap — the compiler enforces that pairing
both ways. [AuthMethod] — a function an unauthenticated visitor may call carries the whole thing as one compiled example.
Signature#
Input(value: email, onEnter: SignIn) — run an action when Enter is pressed in the fieldDescription#
There is no form to post#
In the web platform a <form> serializes its fields and POSTs them to a URL, and pressing Enter is what triggers
that POST. Osy# has no such POST. A bound Input writes its value straight into your component's state — or,
for an entity field, into the row through the page's edit session as you type — so by the time you press Enter
there is nothing to submit: the data is already there. "Submitting" is just running an action that commits it.
So onEnter is not a form-submit affordance dressed up. It is the keyboard peer of onClick: both run an
action, one on click, one on the Enter key. Reach for it wherever pressing Enter should do the same thing a button
would — a login, a search box, an inline "add row" field.
What onEnter takes — an action, not a submit#
onEnter takes an action, exactly like the other event props (onClick/onInput/onChange/onBlur). It can be
a bare action name or one bound with arguments:
[Principal] entity Person { [Required] string Email; }
entity Note {
[Required] string Title;
security { allow create, read, update when IsAuthenticated; }
}
[Page("/notes")] [Render(CSR)]
component NoteSearch() {
string query = "";
string draft = "";
var hits = Note.Where(n => n.Title == query).ToList();
action Search() { /* the query is already in state — this is where you act on it */ }
action AddItem(string title) { var n = new Note { Title = title }; draft = ""; }
render {
Stack(gap: 3) {
Input(value: query, onEnter: Search); // a bare action name
Input(value: draft, onEnter: () => AddItem(draft)); // bound with an argument
foreach (var h in hits) { Text(h.Title); }
}
}
}Enter while the field is empty still fires — the action decides what to do (a login action with a blank password just fails and leaves you on the page).
Can onEnter go on something other than an Input?#
onEnter is a general event prop, not an Input-only one. Put it on any focusable atom where Enter should act —
an Input, a Pressable, a search box built from a Box. A key that is not Enter does nothing, and an Enter that
is confirming an IME candidate (composing CJK text, say) is ignored, so it never submits the half-typed word.
See also#
- creating & saving data — how a bound field writes state / an entity as you type (the reason there's nothing to post).
- The reactivity & lifecycle model —
on changeand the once-only lifecycle bodies, for reactions that aren't triggered by a key.