fix(fast-html): bind event handlers to correct host inside f-repeat#7331
Open
mohamedmansour wants to merge 1 commit intomicrosoft:mainfrom
Open
fix(fast-html): bind event handlers to correct host inside f-repeat#7331mohamedmansour wants to merge 1 commit intomicrosoft:mainfrom
mohamedmansour wants to merge 1 commit intomicrosoft:mainfrom
Conversation
## Summary Event handlers inside `<f-repeat>` now have their `this` context correctly bound to the host element instead of the repeat item. Fixes microsoft#7329. ## Changes - **`utilities.ts`**: Extracted shared path-building logic from `pathResolver` into `buildResolvedPath` helper. Added `eventOwnerResolver` that resolves the *owner* of a method by walking the same context chain but stopping one segment before the method name (e.g. `c.parent` at nesting level 1). - **`template.ts`**: Changed `.bind(x)` to `.bind(ownerResolver(x, c))` in the `@` event binding branch, using `eventOwnerResolver` to determine the correct `this` target. ## What still works - **Level 0 (no repeat)**: `eventOwnerResolver` returns `x` (the host itself), so behavior is identical to before. - **Self-referencing paths**: Paths like `item.doSomething` that start with the repeat context variable correctly resolve the owner to the repeat item (`x`), not the host. - **Nested repeats**: The context-walking logic respects nesting depth, traversing `parentContext`/`parent` chains as needed. - **All existing tests pass** (365 Chromium + WebKit tests). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
8e9458c to
11db239
Compare
radium-v
requested changes
Mar 20, 2026
Collaborator
There was a problem hiding this comment.
In a repeat directive, the template (second arg) expressions are bound to the result of the data binding result (first arg):
type Item = string;
type Items = Item[];
class MyElement extends FASTElement {
public items: Items = ["one", "two", "three"];
public someValue: string = "some value";
public itemClickHandler(event: Event) {
console.log("item clicked", event);
}
}
export const template = html<MyElement>`
${repeat(
x => x.items, // <-- the data binding object (aka `x` for bindings within the repeat's template)
html<Item, MyElement>`
<!-- the template data binding is `Item`, the template binding context is `MyElement` -->
<button
@click="${(currentItem: Item, thisBindingContext) =>
thisBindingContext.parent.itemClickHandler(thisBindingContext.event)}"
>
${
// bindingContext allows access to the parent in any binding, anywhere in template expressions
(currentItem, bindingContext) => bindingContext.parent.someValue
}
</button>
`
)}
`;In FAST HTML, we need to add a way to access the template binding context from within the repeat template, instead of re-contextualizing all bindings within an f-repeat. Providing access to the context object in any binding expression in declarative templates would be the right way to approach this problem.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Event handlers inside
<f-repeat>now have theirthiscontext correctly bound to the host element instead of the repeat item.Changes
utilities.ts: Extracted shared path-building logic frompathResolverintobuildResolvedPathhelper. AddedeventOwnerResolverthat resolves the owner of a method by walking the same context chain but stopping one segment before the method name (e.g.c.parentat nesting level 1).template.ts: Changed.bind(x)to.bind(ownerResolver(x, c))in the@event binding branch, usingeventOwnerResolverto determine the correctthistarget.What still works
eventOwnerResolverreturnsx(the host itself), so behavior is identical to before.item.doSomethingthat start with the repeat context variable correctly resolve the owner to the repeat item (x), not the host.parentContext/parentchains as needed.Fixes #7329.