Skip to content

Commit

Permalink
fix(engine): fixing event target from slotted element (#359)
Browse files Browse the repository at this point in the history
* fix(engine): fixing event target from slotted element

* fix(engine): linting

* fix(engine): linting

* fix(engine): pr fixes
  • Loading branch information
davidturissini authored May 31, 2018
1 parent 01c7eb8 commit 594e508
Show file tree
Hide file tree
Showing 14 changed files with 110 additions and 9 deletions.
11 changes: 3 additions & 8 deletions packages/lwc-engine/src/framework/api.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import assert from "./assert";
import { vmBeingRendered, invokeEventListener, EventListenerContext } from "./invoker";
import { vmBeingRendered } from "./invoker";
import { freeze, isArray, isUndefined, isNull, isFunction, isObject, isString, ArrayPush, assign, create, forEach, StringSlice, StringCharCodeAt, isNumber, isTrue, hasOwnProperty } from "./language";
import { EmptyArray, SPACE_CHAR, ViewModelReflection, resolveCircularModuleDependency } from "./utils";
import { renderVM, createVM, appendVM, removeVM, VM, getCustomElementVM, Slotset, allocateInSlot } from "./vm";
import { ComponentConstructor } from "./component";
import { VNode, VNodeData, VNodes, VElement, VComment, VText, Hooks } from "../3rdparty/snabbdom/types";
import { patchShadowDomEvent, isValidEventForCustomElement } from "./events";
import { getWrappedTemplateListener } from "./events";

export interface RenderAPI {
s(slotName: string, data: VNodeData, children: VNodes, slotset: Slotset): VNode;
Expand Down Expand Up @@ -410,12 +410,7 @@ export function b(fn: EventListener): EventListener {
throw new Error();
}
const vm: VM = vmBeingRendered;
return function handler(event: Event) {
if (isValidEventForCustomElement(event)) {
patchShadowDomEvent(vm, event);
invokeEventListener(vm, EventListenerContext.COMPONENT_LISTENER, fn, vm.component, event);
}
};
return getWrappedTemplateListener(vm, fn);
}

// [k]ey function
Expand Down
20 changes: 19 additions & 1 deletion packages/lwc-engine/src/framework/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from "./dom/node";
import { VM, OwnerKey, getElementOwnerVM, getCustomElementVM } from "./vm";
import { isNull, ArraySplice, ArrayIndexOf, create, ArrayPush, isUndefined, isFunction, getOwnPropertyDescriptor, defineProperties, isTrue } from "./language";
import { isRendering, vmBeingRendered, invokeEventListener, EventListenerContext, componentEventListenerType } from "./invoker";
import { isRendering, vmBeingRendered, invokeEventListener, EventListenerContext, componentEventListenerType, invokeComponentCallback } from "./invoker";
import { patchShadowDomTraversalMethods } from "./dom/traverse";

interface WrappedListener extends EventListener {
Expand Down Expand Up @@ -139,6 +139,24 @@ function getWrappedComponentsListener(vm: VM, listener: EventListener): WrappedL
return wrappedListener;
}

// This method is for wrapping event listeners bound in the template.
export function getWrappedTemplateListener(vm: VM, fn: EventListener): EventListener {
if (process.env.NODE_ENV !== 'production') {
assert.vm(vm);
}
return function handler(event: Event) {
if (isValidEventForCustomElement(event)) {
patchShadowDomEvent(vm, event);

// We do not want to call invoker/invokeEventListener because
// that method is for calling events added to the custom element from within.
// Instead, we can just call the component callback directly because the callback
// is guaranteed to not be attached directly to the root or component instance.
invokeComponentCallback(vm, fn, [event]);
}
};
}

function createElementEventListener(vm: VM) {
if (process.env.NODE_ENV !== 'production') {
assert.vm(vm);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
Child
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Element } from 'engine';

export default class Child extends Element {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<template>
<div onclick={handleClick}>
<slot></slot>
</div>
<div class="correct-event-target" if:true={eventTargetIsCorrectTag}>Event target is correct</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Element, track } from 'engine';

export default class XParent extends Element {
@track eventTargetIsCorrectTag = false;
handleClick(evt) {
this.eventTargetIsCorrectTag = evt.target.tagName === 'X-CHILD';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const assert = require('assert');

describe('Event target in slot elements', () => {
const URL = 'http://localhost:4567/slotted-custom-element-event-target/';

before(() => {
browser.url(URL);
});

it('should receive event with correct target', function () {
browser.execute(function () {
document.querySelector('x-child').click();
});
assert.strictEqual(browser.getText('.correct-event-target'), 'Event target is correct');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<x-parent>
<x-child></x-child>
</x-parent>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Element } from 'engine';

export default class SlottedElementEventTarget extends Element {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<template>
<div class="div-click" onclick={handleClick}>
<slot></slot>
</div>
<div class="correct-event-target" if:true={eventTargetIsPTag}>Event target is correct</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Element, track } from 'engine';

export default class Child extends Element {
@track eventTargetIsPTag = false;
handleClick(evt) {
this.eventTargetIsPTag = evt.target.tagName === 'P';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const assert = require('assert');

describe('Event target in slot elements', () => {
const URL = 'http://localhost:4567/slotted-native-element-event-target/';

before(() => {
browser.url(URL);
});

it('should receive event with correct target', function () {
browser.execute(function () {
document.querySelector('p').click();
});
assert.strictEqual(browser.getText('.correct-event-target'), 'Event target is correct');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<x-child>
<p>Click Me</p>
</x-child>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Element } from 'engine';

export default class SlottedElementEventTarget extends Element {

}

0 comments on commit 594e508

Please sign in to comment.