Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular click event triggers on entire component in recursive nested component

Tags:

angular

I have 2 components - list view component detail component. The detail component is being rendered recursively and has a click handler.

List View Component

HTML:

<app-basket-item-detail *ngFor="let rootBasketItem of rootBasketItems$ | async"
                        [basketItemId]="rootBasketItem.basketItemId"
                        [basketItems]="allBasketItems$ | async"
                        [offeringsCache]="offeringsCache$ | async"
                        (removeBasketItem)="removeBasketItem($event)">
</app-basket-item-detail>

Code:

@Component({
  selector: 'app-basket-item-list-view',
  templateUrl: './basket-item-list-view.component.html',
  styleUrls: ['./basket-item-list-view.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class BasketItemListViewComponent {
  rootBasketItems$: Observable<Array<BasketItem>>;
  allBasketItems$: Observable<Array<BasketItem>>;
  offeringsCache$: Observable<any>;

  constructor(private store: Store<fromRoot.State>) {
    this.rootBasketItems$ = store.select(fromRoot.getRootBasketItems);
    this.allBasketItems$ = store.select(fromRoot.getBasketItemsMap);
    this.offeringsCache$ = store.select(fromRoot.getOfferingsCache);
  }

  removeBasketItem(basketItem) {
    this.store.dispatch(new basketActions.RemoveBasketItem(basketItem));
  }
}

Detail Component (recursive detail component)

HTML:

<ul class="basket-item-list">
  <li class="basket-item-action justify-content-between" [ngClass]="basketItem?.action.toLowerCase()">
    <span>{{ offeringsCache[basketItemId]?.description }}</span>
    <button class="close" (click)="removeBasketItem.emit(basketItem)">
      <span>&times;</span>
    </button>
  </li>

  <app-basket-item-detail *ngFor="let childBasketItemId of basketItem.children"
                          [basketItemId]="childBasketItemId"
                          [basketItems]="basketItems"
                          [offeringsCache]="offeringsCache"
                          (click)="removeBasketItem.emit(basketItems[childBasketItemId])">
  </app-basket-item-detail>
</ul>

Code:

@Component({
  selector: 'app-basket-item-detail',
  templateUrl: './basket-item-detail.component.html',
  styleUrls: ['./basket-item-detail.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class BasketItemDetailComponent implements OnInit {
  @Input() basketItemId: string;
  @Input() basketItems: Array<BasketItem> = [];
  @Input() offeringsCache: [string, BasketItem] = [undefined, undefined];

  @Output() removeBasketItem = new EventEmitter<BasketItem>();

  basketItem: BasketItem;
  offering: ProductOffering;

  ngOnInit(): void {
    this.basketItem = this.basketItems[this.basketItemId];
    this.offering = this.offeringsCache[this.basketItemId];
  }

}

Problem

The view where the list is rendered looks like this: Basket View

What is giving me a headache is that the click event is also triggering not only when I click the X, but it also triggers when I click on the li element. Is there a cure for that? I have been trying everything I can think of to stop it from behaving like that. I want the click events only be handled by the button.

Any ideas?

like image 225
Vaelyr Avatar asked Nov 06 '25 14:11

Vaelyr


1 Answers

You might need to stop propagation. The click event is bubbling:

(click)="removeBasketItem.emit(basketItem);$event.stopPropagation()"
like image 60
Günter Zöchbauer Avatar answered Nov 09 '25 09:11

Günter Zöchbauer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!