feat: on:event|detail modifier

pull/5099/head
Bob Fanger 5 years ago
parent b56829c7b8
commit 186eda50d6

@ -474,6 +474,7 @@ The following modifiers are available:
* `capture` — fires the handler during the *capture* phase instead of the *bubbling* phase
* `once` — remove the handler after the first time it runs
* `self` — only trigger handler if event.target is the element itself
* `detail` — calls the handler with the event.detail value, instead of the event object.
Modifiers can be chained together, e.g. `on:click|once|capture={...}`.

@ -69,7 +69,8 @@ const valid_modifiers = new Set([
'capture',
'once',
'passive',
'self'
'self',
'detail'
]);
const passive_events = new Set([

@ -102,10 +102,10 @@ export default class InlineComponent extends Node {
this.handlers.forEach(handler => {
handler.modifiers.forEach(modifier => {
if (modifier !== 'once') {
if (['once', 'detail'].indexOf(modifier) === -1) {
component.error(handler, {
code: 'invalid-event-modifier',
message: `Event modifiers other than 'once' can only be used on DOM elements`
message: `Event modifiers other than 'once' and 'detail' can only be used on DOM elements`
});
}
});

@ -42,6 +42,7 @@ export default class EventHandlerWrapper {
if (this.node.modifiers.has('preventDefault')) snippet = x`@prevent_default(${snippet})`;
if (this.node.modifiers.has('stopPropagation')) snippet = x`@stop_propagation(${snippet})`;
if (this.node.modifiers.has('self')) snippet = x`@self(${snippet})`;
if (this.node.modifiers.has('detail')) snippet = x`@detail(${snippet})`;
const args = [];

@ -391,6 +391,7 @@ export default class InlineComponentWrapper extends Wrapper {
const event_handler = new EventHandler(handler, this);
let snippet = event_handler.get_snippet(block);
if (handler.modifiers.has('once')) snippet = x`@once(${snippet})`;
if (handler.modifiers.has('detail')) snippet = x`@detail(${snippet})`;
return b`${name}.$on("${handler.name}", ${snippet});`;
});

@ -85,6 +85,13 @@ export function self(fn) {
};
}
export function detail(fn) {
return function(event) {
// @ts-ignore
fn.call(this, event.detail);
};
}
export function attr(node: Element, attribute: string, value?: string) {
if (value == null) node.removeAttribute(attribute);
else if (node.getAttribute(attribute) !== value) node.setAttribute(attribute, value);

@ -0,0 +1,11 @@
<script>
import { createEventDispatcher } from 'svelte';
export let item
const dispatch = createEventDispatcher()
</script>
<button on:click={() => dispatch('select', item)}>
{item}
</button>

@ -0,0 +1,13 @@
export default {
html: `
<button>apple</button>
`,
async test({ assert, component, target, window }) {
const button = target.querySelector('button');
const event = new window.MouseEvent('click');
await button.dispatchEvent(event);
assert.equal(component.selected, "apple");
}
};

@ -0,0 +1,11 @@
<script>
import Row from './Row.svelte';
export let selected ;
function handle_select(item) {
selected = item
}
</script>
<Row on:select|detail={handle_select} item="apple" />

@ -0,0 +1,14 @@
export default {
html: `
<button>click me</button>
`,
async test({ assert, component, target, window }) {
const button = target.querySelector('button');
const event = new window.CustomEvent('click', { detail: 1 });
await button.dispatchEvent(event);
assert.ok(component.button === 1);
}
};

@ -0,0 +1,9 @@
<script>
export let button
function handle_click(detail) {
button = detail
}
</script>
<button on:click|detail={handle_click}>click me</button>

@ -1,5 +1,5 @@
[{
"message": "Event modifiers other than 'once' can only be used on DOM elements",
"message": "Event modifiers other than 'once' and 'detail' can only be used on DOM elements",
"code": "invalid-event-modifier",
"start": {
"line": 6,

@ -1,5 +1,5 @@
[{
"message": "Valid event modifiers are preventDefault, stopPropagation, capture, once, passive or self",
"message": "Valid event modifiers are preventDefault, stopPropagation, capture, once, passive, self or detail",
"code": "invalid-event-modifier",
"start": {
"line": 1,

Loading…
Cancel
Save