How do I trigger an alert/swal function once and not repeatedly?

Viewed 175

I am new to Angular.

I have an app with two variables that indicate the status of a financial transaction. The variables are: tab1TrxMessage that stores any messages and tab1TrxStatus that indicate a transactions status either being: Failed, is successful or is pending. When a transaction has failed, I would like the user to recieve a swal alert/notification similar to this:

swal({
       title:'Error!',
       text: 'Warning... Transaction failed!',
       type: 'error',
       confirmButtonText: 'Ok',
       confirmButtonColor: '#ff754f'
     });

Currently, my code looks like this:

../component.html

<div class="sign-btn text-center">
  <a class="btn btn-lg text-white">
    <span *ngIf="tab1TrxMessage">{{tab1TrxMessage}}</span>
    <span *ngIf="!tab1TrxMessage && tab1TrxStatus != 'Success'">Failed</span>
    <span *ngIf="transactionFailed()">Failed</span>
  </a>
</div>

With specific attention on the transactionFailed() function...

../component.ts

public transactionFailed() {

    if(this.tab1TrxMessage == 'Failed: Cancelled by User' && this.tab1TrxStatus != 'Success') {

        console.log("You are in transactionFailed!")

        swal({
           title:'Error!',
           text: 'Warning... Transaction failed!',
           type: 'error',
           confirmButtonText: 'Ok',
           confirmButtonColor: '#ff754f'
         });

         return true;
    }

    return false;
}

The code above, when a transaction fails yields: You are in transactionFailed! multiples times in the browser console...

console print out

...and so does the swal alert with Warning... Transaction failed! repeatedly popping up.

Is there a better way to resolve this so that the swal alert only displays ONCE per failed transaction?

Looking forward to your help.

3 Answers

Make a counter which will run your code only once. For eg.

failedTransactionCntr = 0;
public transactionFailed() {

    if(this.tab1TrxMessage == 'Failed: Cancelled by User' && this.tab1TrxStatus != 'Success') {

        console.log("You are in transactionFailed!")
        if (this.failedTransactionCntr == 0) {
          swal({
           title:'Error!',
           text: 'Warning... Transaction failed!',
           type: 'error',
           confirmButtonText: 'Ok',
           confirmButtonColor: '#ff754f'
         });
         this.failedTransactionCntr ++;
        }
         return true;
    }

    return false;
}

It happens due to the your change detection strategy and method transactionFailed() function will be called every time Angular runs change detection. The reason why it happens is because updating DOM is part of change detection and Angular needs to call transactionFailed() to know what value to use for DOM update.

You can change changeDetectionStrategy to onPush to avoid transactionFailed() to be called multiple times.

@Component({
 selector: 'your-component',
 templateUrl: './your.component.html',
 styleUrls: ['./your.component.css'],
 changeDetection: ChangeDetectionStrategy.OnPush // this line
})

export class YourComponent {

}

However, it is necessary to manually call method detectChanges() when you want the change detection to run:

constructor(private ref: ChangeDetectorRef) {
    this.ref.detach();
}

start() {
    this.fooVariable = 'This is a foo vaiable';
    this.ref.detectChanges();
}

You can read more about Change detection strategies here

If you are interested in it being valid only once, you can very well use a flag. For example:

lFlagtransfailed = false; 
public transactionFailed() {

    if(this.tab1TrxMessage == 'Failed: Cancelled by User' && this.tab1TrxStatus != 'Success' && lFlagtransfailed == false) { 

        console.log("You are in transactionFailed!")
        lFlagtransfailed = true;
        swal({
           title:'Error!',
           text: 'Warning... Transaction failed!',
           type: 'error',
           confirmButtonText: 'Ok',
           confirmButtonColor: '#ff754f'
         });

         return true;
    }

    return false;
}

Related