Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,63 @@ private static bool TryGetParentFormElementSpecialCase(
IHtmlButtonElement { Type: "submit", Form: not null } button => button.Form,
_ => null
};

// If form is still null, try to find it by the form attribute for submit buttons/inputs
if (form is null && element.HasAttribute("form"))
{
var isSubmitElement = element switch
{
IHtmlInputElement { Type: "submit" } => true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the HTML standard allow for an tag to be used in this scenario? If so, also add a test case for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the HTML5 standard allows <input type="submit"> with the form attribute. Added test cases in commit 36a5d18 for both button and input elements outside forms using the form attribute.

IHtmlButtonElement { Type: "submit" } => true,
_ => false
};

if (isSubmitElement)
{
var formId = element.GetAttribute("form");
if (!string.IsNullOrEmpty(formId))
{
// Try to find the form element by traversing up to find a common ancestor
// and then searching down for the form
form = FindFormById(element, formId);
}
}
}

return form is not null
&& form.TryGetEventId(Htmlizer.ToBlazorAttribute("onsubmit"), out eventId);
}

private static IHtmlFormElement? FindFormById(IElement element, string formId)
{
// First try the owner's GetElementById (most efficient if it works)
var formByOwner = element.Owner?.GetElementById(formId) as IHtmlFormElement;
if (formByOwner is not null)
{
return formByOwner;
}

// If GetElementById didn't work (which can happen with Blazor's incremental DOM rendering),
// traverse up the DOM tree to find a common ancestor and search its children
// This handles cases where the button and form are siblings or in different subtrees
var current = element.Parent as IElement;
while (current is not null)
{
// Search children of current element for the form with matching ID
foreach (var child in current.Children)
{
if ((child.Id == formId || child.GetAttribute("id") == formId) && child is IHtmlFormElement htmlForm)
{
return htmlForm;
}
}

// Move up to parent to widen the search
current = current.Parent as IElement;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot I do not think this is right. There is no incremental DOM rendering in the context of bUnit, right @linkdotnet

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct. Updated the comment in commit 32d7373 to remove the incorrect reference to "Blazor's incremental DOM rendering". The actual reason is that AngleSharp's document ID indexing doesn't always include all elements, so the fallback traversal is needed.


return null;
}

private static bool EventIsDisabled(this IElement element, string eventName)
{
Expand Down
Loading