Nativescript-angular: Button (tap) event runs twice

Created on 28 Jan 2019  路  12Comments  路  Source: NativeScript/nativescript-angular

So this is a strange one, and was hard to reproduce.

Environment
Whatever version play.nativescript.org is running.
However, I'm seeing the same in my own setup with nativescript-angular 7.1.2

ONLY TESTED ON IOS!

Describe the bug
The tap event runs twice

To Reproduce
Check https://play.nativescript.org/?template=play-ng&id=oSZ0t7&v=7
The proof of concept is in the home.component.

Click the button once, and check the logs.

....
If you remove the *ngIf from the button it will run twice on the first click, and then only once the following clicks. I added a few setTimeouts to cycle the component, which will cause the problem to be apparent on every click.

It also seems related to the HostListener on the btnClick directive I'm using, which listens for the touch event. I'll leave you to figure out whats what.

Expected behavior
I expect the tap event to behave, and only trigger once.

Sample project
https://play.nativescript.org/?template=play-ng&id=oSZ0t7&v=7

needs more info

Most helpful comment

@NickIliev

@tahir-jamil you can use this solution

You call that a solution ? I call that a dirty workaround.

I still have a lot of unwunted double tap, on ios and android

Please reopen

All 12 comments

Hi @larssn,
Thank you for the provided sample project.
I tested on my side however the event was triggered once when I tap on the Button component on both platforms(Android and iOS). For me, it sounds like a temporary sync issue. Can you try restarting the preview app and rerun it.

Sorry, I seemed to have posted an older playground version link. I've bumped the version to 7 in the OP, which will show the problem.

Hi @larssn,
I rechecked the project, and it seems the issue is caused by the custom ButtonClickDirective, that you have registered in the home.module.ts. If you remove it from the declarations, the problem will disappear.
home.module.ts

import { HomeRoutingModule } from "./home-routing.module";
import { HomeComponent } from "./home.component";
import { ButtonClickDirective } from "./button-click.directive";

@NgModule({
    imports: [
        NativeScriptUISideDrawerModule,
        NativeScriptUIListViewModule,
        NativeScriptUICalendarModule,
        NativeScriptUIChartModule,
        NativeScriptUIDataFormModule,
        NativeScriptUIAutoCompleteTextViewModule,
        NativeScriptUIGaugeModule,
        NativeScriptCommonModule,
        HomeRoutingModule,
        NativeScriptFormsModule
    ],
    declarations: [
        HomeComponent,
        // ButtonClickDirective
    ],
    schemas: [
        NO_ERRORS_SCHEMA
    ]
})
export class HomeModule { }

I hope you're not suggesting we can't use directives in our Angular app? ;)
The bug is not in the directive, mind you.

Anyway, several workarounds can be found, but that doesn't fix the underlying issue.
Here's a few:

  • Converting the button to a Label fixes the problem.
  • Removing the directive fixes the problem as you said (even though the directive doesn't trigger any events, it only _listens_ to the touch event)

Edit
Our current workaround in the app is to convert all buttons to labels, but we lose out of a bit of built-in functionality of buttons.

HI @larssn,
Directives can be used in NativeScript Angular project. We are using them in our SDK samples as well. Check out the linkhere. What I meant, was that the current directive is causing the issue. It might be related to the touch event, which you are setting up in the HostListener.

But as I said, if you convert the button to a Label, it works fine, even with the directive.

But lets stress the main point: 2 tap events is an unexpected side-effect to using a directive that listens for touch events. 2 taps should not happen under any circumstance other than the user actually tapping twice.

For the above project example:
https://play.nativescript.org/?template=play-ng&id=oSZ0t7&v=7

The solution for Button is just to do this:

import { Component, OnInit } from "@angular/core";

@Component({
    selector: "Home",
    moduleId: module.id,
    templateUrl: "./home.component.html",
    styleUrls: ['./home.component.css']
})
export class HomeComponent {
    isClicked = false;

    clickMe() {
        if (this.isClicked)
            return;
        this.isClicked = true;

        console.log('Clicked!');

        // THANKS: https://stackoverflow.com/questions/41659822/when-and-why-to-use-a-tick-in-angular-2
        // So the 0 is to make the change detection happen immediately and the empty function is because we don't want to do anything.
        setTimeout(() => {
            this.isClicked = false;
        }, 0);
    }
}

Enjoy.

any update on it?

It still have bugs when you click fast. :'(

any update on it in 2020?

@tahir-jamil you can use this solution

@NickIliev

@tahir-jamil you can use this solution

You call that a solution ? I call that a dirty workaround.

I still have a lot of unwunted double tap, on ios and android

Please reopen

Was this page helpful?
0 / 5 - 0 ratings