-
Notifications
You must be signed in to change notification settings - Fork 13.5k
bug: ion-item click event emitted two times (with ion-input) #29761
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
Comments
This looks to be the same as #28803 (comment). |
@liamdebeasi this seems like a good case for a missing feature: <ion-item [do-not-click-childs]="true" ... I'm building a screen with We need an input flag to disable that click, and that would help my case and this double click stuff too. PS/ this check discards the click inside the input to avoid double-clicks? clickedWithinShadowRoot = this.el.shadowRoot!.contains(target); |
Hey there! I no longer work for Ionic, so I won't be much help in getting this resolved. However, if this issue is important for your use case I recommend adding a thumbs up reaction to the original post in addition to your comment above. |
@liamdebeasi thank you very much! |
@matheo I like the idea too |
@JulienLecoq I had to build this Directive to intercept the // no-toggle.directive.ts
import { DOCUMENT } from '@angular/common';
import { DestroyRef, Directive, ElementRef, OnInit, contentChildren, inject, output } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { IonToggle } from '@ionic/angular/standalone';
import { tap } from 'rxjs';
@Directive({
selector: 'ion-item[no-toggle]',
standalone: true,
})
export class ItemNoToggleDirective implements OnInit {
readonly #document = inject(DOCUMENT);
readonly #destroy = inject(DestroyRef);
readonly #el = inject(ElementRef);
readonly toggle = contentChildren(IonToggle);
readonly onToggle = output<CustomEvent>();
private target?: HTMLInputElement;
private timeout?: ReturnType<typeof setTimeout>;
ngOnInit() {
if (this.#el.nativeElement.tagName !== 'ION-ITEM' || !this.toggle().length) {
throw new Error('"no-toggle" directive must be used on an <ion-item> with an <ion-toggle>');
}
// ion-item clicks the toggle when it's clicked
this.#el.nativeElement.addEventListener('click', this.onItemClick.bind(this));
this.toggle()[0]
.ionChange.pipe(
takeUntilDestroyed(this.#destroy),
tap((event) => this.onChange(event)),
)
.subscribe();
}
onChange(event: CustomEvent) {
// keep the reference to the target element
this.target = event.target as HTMLInputElement;
this.timeout = setTimeout(() => {
// only emit if it's not a ion-item click
this.onToggle.emit(event);
this.target = undefined;
}, 1);
}
onItemClick() {
(this.#document.activeElement as HTMLElement)?.blur();
clearTimeout(this.timeout);
// reset the target element if this was a click on the ion-item
if (this.target) {
this.target.checked = !this.target.checked;
this.target = undefined;
}
}
} |
@matheo Thanks a lot, you inspired me this that ChatGPT built for me cause I'm not a pro of those stuff haha. import { Directive, ElementRef, HostListener, inject, output, } from '@angular/core'
@Directive({
selector: 'ion-item[smartClick]',
})
export class IonItemSmartClickDirective {
private readonly element = inject(ElementRef<HTMLElement>).nativeElement
readonly smartClick = output<MouseEvent>()
@HostListener('click', ['$event'])
handleClick(event: MouseEvent) {
// Ignore synthetic or non-user-initiated click.
if (event.detail === 0) return
// Clone the event with a modified target pointing to ion-item.
const proxyEvent = new MouseEvent(event.type, event)
Object.defineProperty(proxyEvent, 'target', {
value: this.element,
writable: false,
})
this.smartClick.emit(proxyEvent)
}
} |
…nd emit correct element (#30373) Issue number: resolves #29758 resolves #29761 --------- ## What is the current behavior? When an `ion-item` has a click event listener, the following issues occur: 1. **Double Click Events**: - Clicking the padding around interactive elements (`ion-checkbox`, `ion-toggle`, `ion-radio`, `ion-textarea`, `ion-input`) triggers the click event twice. 2. **Incorrect Event Targets**: - For `ion-input` and `ion-textarea`, clicking their native inputs reports the wrong element as the event target. - Clicking the padding within the `native-wrapper` of `ion-input` emits a separate click event with an incorrect target element. ## What is the new behavior? - Fires `firstInteractive.click()` in Item for all interactives (no longer excludes input/textarea). - Stops immediate propagation in item when the click event is in the padding of an item, preventing two click events from firing. - Updates input and textarea to always emit from their host elements `ion-input`/`ion-textarea` instead of the native input elements. - Updates input to make the native input take up 100% height. This is necessary to avoid the `native-wrapper` triggering its own click event when clicking on its padding. - Adds e2e tests to check for the above behavior to avoid future regressions. ## Does this introduce a breaking change? - [ ] Yes - [x] No ## Other information **Dev build**: `8.5.6-dev.11745613928.16440384` **Previews**: - [Checkbox Preview](https://ionic-framework-git-fw-6503-ionic1.vercel.app/src/components/checkbox/test/item) - [Input Preview](https://ionic-framework-git-fw-6503-ionic1.vercel.app/src/components/input/test/item) - [Radio Preview](https://ionic-framework-git-fw-6503-ionic1.vercel.app/src/components/radio/test/item) - [Select Preview](https://ionic-framework-git-fw-6503-ionic1.vercel.app/src/components/select/test/item) - [Textarea Preview](https://ionic-framework-git-fw-6503-ionic1.vercel.app/src/components/textarea/test/item) - [Toggle Preview](https://ionic-framework-git-fw-6503-ionic1.vercel.app/src/components/toggle/test/item) --------- Co-authored-by: Brandy Smith <[email protected]>
Super cool, I'll wait for the stable build to update to it but I'm very excited for this! :) I'll let you know if I find any issues once I have done the update. |
This has been released in 8.5.6. If you run into any other problems please open a new issue. Thank you! |
@brandyscarney is it possible to have a boolean input in the it would be good to have control on that behavior right? |
Prerequisites
Ionic Framework Version
v8.x
Current Behavior
When putting a ion-input inside of an ion-item, the click event on the ion-item is emitted two times when clicking just above or below the ion-input.
Expected Behavior
The click event should be emitted just once.
Steps to Reproduce
Code Reproduction URL
https://github.com/JulienLecoq/bug_ion-item_click_with_ion-input
Ionic Info
Ionic:
Ionic CLI : 7.2.0 (/Users/julien_lecoq/.nvm/versions/node/v20.14.0/lib/node_modules/@ionic/cli)
Ionic Framework : @ionic/angular 8.2.6
@angular-devkit/build-angular : 18.1.4
@angular-devkit/schematics : 18.1.4
@angular/cli : 18.1.4
@ionic/angular-toolkit : 11.0.1
Capacitor:
Capacitor CLI : 6.1.2
@capacitor/android : not installed
@capacitor/core : 6.1.2
@capacitor/ios : not installed
Utility:
cordova-res : not installed globally
native-run : 2.0.1
System:
NodeJS : v20.14.0 (/Users/julien_lecoq/.nvm/versions/node/v20.14.0/bin/node)
npm : 10.7.0
OS : macOS Unknown
Additional Information
No response
The text was updated successfully, but these errors were encountered: