Skip to content

Fix outlet matching for whitespace-separated data-controller values - #911

Open
tchiadeu wants to merge 1 commit into
hotwired:mainfrom
tchiadeu:fix-outlet-whitespace-matching
Open

Fix outlet matching for whitespace-separated data-controller values#911
tchiadeu wants to merge 1 commit into
hotwired:mainfrom
tchiadeu:fix-outlet-whitespace-matching

Conversation

@tchiadeu

@tchiadeu tchiadeu commented Aug 22, 2026

Copy link
Copy Markdown

OutletSet#matchesElement tokenizes the data-controller attribute with a naive .split(" "), splitting only on single literal space characters:

private matchesElement(element: Element, selector: string, outletName: string): boolean {
  const controllerAttribute = element.getAttribute(this.scope.schema.controllerAttribute) || ""
  return element.matches(selector) && controllerAttribute.split(" ").includes(outletName)
}

When a data-controller value is written across multiple lines, for example, generated by a server-side template that formats the attribute with newlines and indentation for readability, every identifier after the first ends up with a trailing newline glued to it ("my-controller\n" instead of "my-controller"). .split(" ") never removes that newline, so .includes(outletName) returns false even though the controller is genuinely connected to that element. The result is a "Missing outlet element" error for an outlet that's actually present.

This is inconsistent with how Stimulus parses data-controller everywhere else. TokenListObserver (responsible for actually connecting controllers) already handles this correctly via .trim().split(/\s+/). This PR applies the same tokenization in OutletSet#matchesElement so outlet resolution matches controller-connection semantics.

Also adds a regression test reproducing a data-controller value split across multiple lines, verifying the outlet is still found.

…oller values

OutletSet#matchesElement tokenized the controller attribute with a
naive `.split(" ")`, only splitting on a single literal space
character. When a data-controller attribute is written across
multiple lines (e.g. generated by server-side templates that format
the value with newlines and indentation), each identifier except the
first ends up with trailing whitespace glued to it, so it never
equals the plain identifier and the outlet lookup silently fails to
find an otherwise correctly connected controller.

TokenListObserver already parses data-controller robustly via
`.trim().split(/\s+/)`. Apply the same tokenization in
OutletSet#matchesElement so outlet resolution is consistent with how
controllers are actually connected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant