Execute form.onsubmit when a form is being submitted

This commit is contained in:
Karl Seguin
2026-02-04 13:45:53 +08:00
parent 3c635532c4
commit 1352315441
2 changed files with 32 additions and 5 deletions

View File

@@ -3264,12 +3264,12 @@ pub fn handleClick(self: *Page, target: *Node) !void {
}, .anchor); }, .anchor);
}, },
.input => |input| switch (input._input_type) { .input => |input| switch (input._input_type) {
.submit => return self.submitForm(element, input.getForm(self)), .submit => return self.submitForm(element, input.getForm(self), .{}),
else => self.window._document._active_element = element, else => self.window._document._active_element = element,
}, },
.button => |button| { .button => |button| {
if (std.mem.eql(u8, button.getType(), "submit")) { if (std.mem.eql(u8, button.getType(), "submit")) {
return self.submitForm(element, button.getForm(self)); return self.submitForm(element, button.getForm(self), .{});
} }
}, },
.select, .textarea => self.window._document._active_element = element, .select, .textarea => self.window._document._active_element = element,
@@ -3299,7 +3299,7 @@ pub fn handleKeydown(self: *Page, target: *Node, event: *Event) !void {
if (target.is(Element.Html.Input)) |input| { if (target.is(Element.Html.Input)) |input| {
if (key == .Enter) { if (key == .Enter) {
return self.submitForm(input.asElement(), input.getForm(self)); return self.submitForm(input.asElement(), input.getForm(self), .{});
} }
// Don't handle text input for radio/checkbox // Don't handle text input for radio/checkbox
@@ -3329,7 +3329,10 @@ pub fn handleKeydown(self: *Page, target: *Node, event: *Event) !void {
} }
} }
pub fn submitForm(self: *Page, submitter_: ?*Element, form_: ?*Element.Html.Form) !void { const SubmitFormOpts = struct {
fire_event: bool = true,
};
pub fn submitForm(self: *Page, submitter_: ?*Element, form_: ?*Element.Html.Form, submit_opts: SubmitFormOpts) !void {
const form = form_ orelse return; const form = form_ orelse return;
if (submitter_) |submitter| { if (submitter_) |submitter| {
@@ -3344,6 +3347,27 @@ pub fn submitForm(self: *Page, submitter_: ?*Element, form_: ?*Element.Html.Form
const form_element = form.asElement(); const form_element = form.asElement();
if (submit_opts.fire_event) {
const submit_event = try Event.initTrusted("submit", .{ .bubbles = true, .cancelable = true }, self);
const onsubmit_handler = form.asHtmlElement().getOnSubmit(self);
var ls: JS.Local.Scope = undefined;
self.js.localScope(&ls);
defer ls.deinit();
try self._event_manager.dispatchWithFunction(
form_element.asEventTarget(),
submit_event,
ls.toLocal(onsubmit_handler),
.{ .context = "form submit" },
);
// If the submit event was prevented, don't submit the form
if (submit_event._prevent_default) {
return;
}
}
const FormData = @import("webapi/net/FormData.zig"); const FormData = @import("webapi/net/FormData.zig");
// The submitter can be an input box (if enter was entered on the box) // The submitter can be an input box (if enter was entered on the box)
// I don't think this is technically correct, but FormData handles it ok // I don't think this is technically correct, but FormData handles it ok

View File

@@ -32,6 +32,9 @@ pub const TextArea = @import("TextArea.zig");
const Form = @This(); const Form = @This();
_proto: *HtmlElement, _proto: *HtmlElement,
pub fn asHtmlElement(self: *Form) *HtmlElement {
return self._proto;
}
fn asConstElement(self: *const Form) *const Element { fn asConstElement(self: *const Form) *const Element {
return self._proto._proto; return self._proto._proto;
} }
@@ -88,7 +91,7 @@ pub fn getLength(self: *Form, page: *Page) !u32 {
} }
pub fn submit(self: *Form, page: *Page) !void { pub fn submit(self: *Form, page: *Page) !void {
return page.submitForm(null, self); return page.submitForm(null, self, .{ .fire_event = false });
} }
pub const JsApi = struct { pub const JsApi = struct {