mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] component: fix wrong behaviour when using t-on on t-component
Before this commit, using t-on on t-component was not correctly implemented by owl: when more than one component shared the same parentelement and have an handler with the same name, the second handler would override the first (using an internal key). With this commit, we simply recreate event handler for each instance of a catcher block. Note that it means that using t-on on components is slightly slower now. Also, this commit fixes an additional issue that was noticed: the catcher block would not update its internal handler properly, so it would not behave properly after being patched. closes #1199
This commit is contained in:
committed by
Sam Degueldre
parent
31b57cbb40
commit
c7bd0ab85c
@@ -6,34 +6,38 @@ type EventsSpec = { [name: string]: number };
|
||||
type Catcher = (child: VNode, handlers: any[]) => VNode;
|
||||
|
||||
export function createCatcher(eventsSpec: EventsSpec): Catcher {
|
||||
let setupFns: any[] = [];
|
||||
let removeFns: any[] = [];
|
||||
for (let name in eventsSpec) {
|
||||
let index = eventsSpec[name];
|
||||
let { setup, remove } = createEventHandler(name);
|
||||
setupFns[index] = setup;
|
||||
removeFns[index] = remove;
|
||||
}
|
||||
let n = setupFns.length;
|
||||
const n = Object.keys(eventsSpec).length;
|
||||
|
||||
class VCatcher {
|
||||
child: VNode;
|
||||
handlers: any[];
|
||||
handlerData: any[];
|
||||
handlerFns: any[] = [];
|
||||
|
||||
parentEl?: HTMLElement | undefined;
|
||||
afterNode: Node | null = null;
|
||||
afterNode: Text | null = null;
|
||||
|
||||
constructor(child: VNode, handlers: any[]) {
|
||||
this.child = child;
|
||||
this.handlers = handlers;
|
||||
this.handlerData = handlers;
|
||||
}
|
||||
|
||||
mount(parent: HTMLElement, afterNode: Node | null) {
|
||||
this.parentEl = parent;
|
||||
this.afterNode = afterNode;
|
||||
this.child.mount(parent, afterNode);
|
||||
this.afterNode = document.createTextNode("");
|
||||
parent.insertBefore(this.afterNode, afterNode);
|
||||
this.wrapHandlerData();
|
||||
for (let name in eventsSpec) {
|
||||
const index = eventsSpec[name];
|
||||
const handler = createEventHandler(name);
|
||||
this.handlerFns[index] = handler;
|
||||
handler.setup.call(parent, this.handlerData[index]);
|
||||
}
|
||||
}
|
||||
|
||||
wrapHandlerData() {
|
||||
for (let i = 0; i < n; i++) {
|
||||
let handler = this.handlers[i];
|
||||
let handler = this.handlerData[i];
|
||||
// handler = [...mods, fn, comp], so we need to replace second to last elem
|
||||
let idx = handler.length - 2;
|
||||
let origFn = handler[idx];
|
||||
@@ -49,20 +53,24 @@ export function createCatcher(eventsSpec: EventsSpec): Catcher {
|
||||
currentNode = currentNode.nextSibling;
|
||||
}
|
||||
};
|
||||
setupFns[i].call(parent, this.handlers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
moveBefore(other: VCatcher | null, afterNode: Node | null) {
|
||||
this.afterNode = null;
|
||||
this.child.moveBefore(other ? other.child : null, afterNode);
|
||||
this.parentEl!.insertBefore(this.afterNode!, afterNode);
|
||||
}
|
||||
|
||||
patch(other: VCatcher, withBeforeRemove: boolean) {
|
||||
if (this === other) {
|
||||
return;
|
||||
}
|
||||
this.handlers = other.handlers;
|
||||
this.handlerData = other.handlerData;
|
||||
this.wrapHandlerData();
|
||||
for (let i = 0; i < n; i++) {
|
||||
this.handlerFns[i].update.call(this.parentEl!, this.handlerData[i]);
|
||||
}
|
||||
|
||||
this.child.patch(other.child, withBeforeRemove);
|
||||
}
|
||||
|
||||
@@ -72,9 +80,10 @@ export function createCatcher(eventsSpec: EventsSpec): Catcher {
|
||||
|
||||
remove() {
|
||||
for (let i = 0; i < n; i++) {
|
||||
removeFns[i].call(this.parentEl!);
|
||||
this.handlerFns[i].remove.call(this.parentEl!);
|
||||
}
|
||||
this.child.remove();
|
||||
this.afterNode!.remove();
|
||||
}
|
||||
|
||||
firstNode(): Node | undefined {
|
||||
|
||||
Reference in New Issue
Block a user