Android `(tap)` binding issues
jamescodesthings opened this issue · 3 comments
Environment
NS Info
✔ Component nativescript has 7.2.0 version and is up to date.
⚠ Update available for component @nativescript/core. Your current version is 7.1.4 and the latest available version is 7.2.1.
✔ Component @nativescript/ios has 7.2.0 version and is up to date.
✔ Component @nativescript/android has 7.0.1 version and is up to date.
Npm List
@nativescript/template-hello-world-ng@7.0.9 /Users/jamesmacmillan/projects/demo/demo-tap-issue
├── @angular/animations@11.0.9
├── @angular/common@11.0.9
├── @angular/compiler@11.0.9
├── @angular/compiler-cli@11.0.9
├── @angular/core@11.0.9
├── @angular/forms@11.0.9
├── @angular/platform-browser@11.0.9
├── @angular/platform-browser-dynamic@11.0.9
├── @angular/router@11.0.9
├── @nativescript/android@7.0.1
├── @nativescript/angular@11.0.1
├── @nativescript/core@7.1.4
├── @nativescript/ios@7.2.0
├── @nativescript/theme@3.0.1
├── @nativescript/types@7.0.4
├── @nativescript/webpack@4.0.1
├── @ngtools/webpack@11.0.7
├── nativescript@7.2.0
├── reflect-metadata@0.1.13
├── rxjs@6.6.3
├── sass@1.32.7
├── typescript@4.0.7
└── UNMET PEER DEPENDENCY zone.js@0.11.3
Describe the bug
On android, if i bind to an event emitter on a component with the name (tap)
it gets emitted twice if one of the children has a tap binding. On iOS there's no issue.
See example repo, it's more difficult to describe the scenario than it is to demo it:
https://github.com/jamescodesthings/demo-tap-issue
I'm seeing this all over, and it's relatively recent but I've only spotted it in newer versions of ns@7.
To Reproduce
https://github.com/jamescodesthings/demo-tap-issue
Expected behavior
See the ios-demo side of the repo, that's what should be happening
Sample project
https://github.com/jamescodesthings/demo-tap-issue
Additional context
I'm also seeing a similar issue if i have a layout like Page -> Custom Component -> ListView -> Custom Component -> GridLayout(tap)
which can be seen on the demo-2 component in the example repo.
@jamescodesthings I have to investigate it some more, but I believe this happens because tap is a event that any view can have, and an angular view is a ProxyViewContainer, so you're binding both to an event emitter and a view event.
This shouldn't happen to a Button (instead of a Label) because the Button doesn't propagate the tap up, but Label does. This is an inconsistency on nativescript core.
I also believe this happens on angular web on (click).
The best approach here is to not use events that conflict with core events, or maybe using HostProperty to set isUserInteractionEnabled to false to discard any events on the angular view itself.
Cheers for getting back to me. I like the idea of using the HostProperty, for now I've worked around by renaming the event to 'tapped' which stops the conflict.
I'm uncertain if it's the ProxyViewContainer, why we'd only see the issue on Android?
If that's the case then the opposite is the problem, iOS doesn't bind to (tap)
on custom components.
@jamescodesthings on android it works like this:
If things have native tap (like button, which has onClick), they handle tap natively and it doesn't get bubbled up. If it doesn't, then they map every touch event against an event detector. The touch is processed then passed up the (JS) nativescript tree. Since ProxyViewContainer is a View, it processes the tap as well and triggers a tap as the tap was not captured by the Label (which is why a button should work).
On iOS everything uses native delegates, so since ProxyViewContainer is not a real view, it won't trigger a tap. I've gone through it a little more in-depth in my RFC discussion: NativeScript/rfcs#13