Search code examples
jqueryangulareventemitterbootstrap-popover

How to emit event in angular only for particular element?


I am creating a directive in angular to make the confirmation popover using the bootstrap popover, though I am mixing jQuery to achieve it. In directive file code is like:

@Output() confirmed = new EventEmitter();

constructor(
    private _ElementRef: ElementRef
) { }

ngOnInit() {
    $(this._ElementRef.nativeElement).popover({
        container: 'body',
        html: true,
        content: `
        <div class="text-center">
            <span class="d-block">Are you sure?</span>
            <div class="btn-group btn-group-sm mt-1">
                <button class="btn btn-outline-danger py-0" id="btn-confirm">Yes</button>
                <button class="btn btn-outline-primary py-0">No</button>
            </div>
        </div>`,
        placement: 'top',
        trigger: 'focus',
        boundary: 'window'
    });


    $('body').on('click', '#btn-confirm', () => {
        this.confirmed.emit();
    });

And in the component's template file:

<input appConfirmation (confirmed)="confirmed()" type="submit" value="Sign up" class="btn btn-primary btn-block">
<input appConfirmation (confirmed)="confirmed()" type="submit" value="Sign up" class="btn btn-primary btn-block">
<input appConfirmation (confirmed)="confirmed()" type="submit" value="Sign up" class="btn btn-primary btn-block">

Whenever I click the #btn-confirm the confirmed() method is executed three times in the component. How can I emit the event for a particular button for a single time?


Solution

  • Scope your variables correctly, put your hooks on the right functions, follow the HTML rules (IDs are unique), use the framework to its full potential, and I would suggest stop using JQuery, but since you use it, let's roll with it.

    @HostListener('click', ['$event'])
    click(event) {
    
      const ID = Math.random().toString(36).slice(-8);
    
      $(this._ElementRef.nativeElement).popover({
        container: 'body',
        html: true,
        content: `
        <div class="text-center">
            <span class="d-block">Are you sure?</span>
            <div class="btn-group btn-group-sm mt-1">
                <button class="btn btn-outline-danger py-0" id="${ID}">Yes</button>
                <button class="btn btn-outline-primary py-0">No</button>
            </div>
        </div>`,
        placement: 'top',
        trigger: 'focus',
        boundary: 'window'
      });
    
    
      $('body').on('click', `#${ID}`, () => {
        this.confirmed.emit();
      });
    }
    

    This bins the click event to the function, meaning you only create a popover on click and it gets destroyed when you confirm. Your IDs become unique, creating no more conflicts. To ensure that, they're created dynamically.