New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds Event Handler Options #847
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 478ddcb:
|
Codecov Report
@@ Coverage Diff @@
## master #847 +/- ##
==========================================
- Coverage 97.64% 94.81% -2.83%
==========================================
Files 127 127
Lines 8034 8049 +15
Branches 1861 1869 +8
==========================================
- Hits 7845 7632 -213
- Misses 189 417 +228
Continue to review full report at Codecov.
|
@samends I don't think the current implementation correctly works with import { renderer, create, tsx, invalidator } from "@dojo/framework/core/vdom";
const factory = create({ invalidator });
const App = factory(function App({ middleware: { invalidator } }) {
return (
<div>
<button
onclick={{
once: true,
handler: () => {
console.log("hello world");
invalidator();
}
}}
>
Click
</button>
</div>
);
});
const r = renderer(() => <App />);
r.mount(); |
@@ -301,7 +301,11 @@ describe('harness', () => { | |||
const h = harness(() => w(MyWidget, {})); | |||
h.trigger('*[key="span"]', (node: WNode | VNode) => { | |||
if (isVNode(node)) { | |||
return node.properties.onclick; | |||
const onclick = node.properties.onclick; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come we had to change this here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This now needs to check if the event is an object with handler
or an function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a test though isn't it, and you haven't changed the test? so why has the vnode changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I now that this is a type guard, and you can't possibly ever get to the handler code - so I think this would be better as just a type cast instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm so the more I think about this I think the more problematic this type change is for users downstream. Given how this is not the common use case, have we considered not changing VNodeProperties
at all, and instead creating a utility function that basically creates a function with properties decorated on it (thus adhering to the existing interface?). so something like:
<button onclick={ eventWithOptions({ capture: true }, () => console.log('onclick')) }>Button</button>
or perhaps even nicer if we just want to solve the passive
case for now like the issue raised:
<button onscroll={ passive(() => console.log('onscroll')) } >Button</button>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I haven't considered something like that but it would make the typing alot easier
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me look into this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this to work you would need to change the types so that the onscroll
function could optionally take a function with any parameters
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going back to this problem what your suggesting would still require a change to the event types so we'd still need to check to see if there's a handler here. What could work instead is if we optionally took two values for events?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@samends I'm still not sure what the problem with a wrapper function is with regards to types? It looks like you could do something like this without requiring any changes to types (as it works for v7), and then hook into the property on the handler in the vdom to deal with it?
https://codesandbox.io/s/wonderful-sound-kijth?file=/src/main.tsx
Does this change work with the test renderer? |
@@ -1609,7 +1648,14 @@ export function renderer(renderer: () => RenderResult): Renderer { | |||
setValue(domNode, propValue, previousValue); | |||
} else if (propName !== 'key' && propValue !== previousValue) { | |||
const type = typeof propValue; | |||
if (type === 'function' && propName.lastIndexOf('on', 0) === 0 && includesEventsAndAttributes) { | |||
if (type === 'object' && propValue && 'handler' in propValue) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this also need the includesEventsAndAttributes
to ensure that events don't get registered twice? Another thing would be that we probably need to add support for this new style of event handlers when using dom()
function (https://github.com/dojo/framework/blob/master/src/core/interfaces.d.ts#L171)
When support has been added for that then it might make sense to put all the logic handling either a function or object with a handler inside the updateEvent
function.
Hmm @matt-gadd maybe we shouldn't offer |
@@ -1296,7 +1335,7 @@ export function renderer(renderer: () => RenderResult): Renderer { | |||
}; | |||
} | |||
|
|||
domNode.addEventListener(eventName, callback); | |||
domNode.addEventListener(eventName, callback, options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you will have to do a check here to support IE11, as it doesn't take an options bag so passing anything truthy to it will mean it does a capture.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So IE doesn't seem to have an equivalent here, could we still implement this with a note saying IE doesn't support event options?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah none of the options bag is implemented in IE other than capture and it’s a Boolean as the third parameter I believe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup that’s correct, it doesn’t error passing an object bag but it does consider it “truthy” so capture is enabled. We’ll need to sniff IE11 and and not pass the options bag at all I think. That can be documented that the “passive” helper isn’t supported in IE11
Closing as resolved in #856 |
Type: Feature
The following has been addressed in the PR:
prettier
as per the readme code style guidelinesAdds ability to use event handler options as described here: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener. The syntax would be the following:
As describe in the open issue, this would allow events on elements to be label as
passive
, preventing the warning on chrome. This will also allow a developer to use the optionscapture
andonce
.Resolves #810