3

I display on page an array of arrays of objects. And every object has a click event. I want to replace that many clicks events (now it is more than three thousand click events) by one click on wrapper. For example, current code

<div *ngFor="var service of services">
  <div *ngFor="var cat of service.cats">
    <div (click)="catClick(cat)">{{cat.name}}</div>
    <div (click)="increaseQuantity(cat)">+</div>
    <div (click)="decreaseQuantity(cat)">-</div>
  </div>
</div>

Desired code

<div (click)="someCommonFunc($event)">
  <div *ngFor="var service of services">
    <div *ngFor="var cat of service.cats">
      <div>{{cat.name}}</div>
      <div>+</div>
      <div>-</div>
    </div>
  </div>
</div>

But in event.target I get only HTML code of element. How can I get an angular object, which has been bound on that html-element?

4
  • Why? What's the concrete problem you're trying to solve? Commented Apr 19, 2019 at 19:46
  • I want to decrease number of listeners Commented Apr 19, 2019 at 19:48
  • OK, but why? What's the problem you're facing with these listeners? Have you proven that these click listeners cause a significant performance problem, which justifies your attempt to do things in a non obvious, complex way? Commented Apr 19, 2019 at 19:50
  • The problem as I see it is not that you have 3000 click events it is that you are showing 1000 items on the page which in turn requires those click events. Add some filtering and limit the number of items on the page/screen to a reasonable amount like 50 or even 100. There are various paging techniques and filtering controls you could use to make the experience more manageable for a user. No one wants to scroll through 1000 items to find the one they want. Commented Apr 19, 2019 at 19:51

2 Answers 2

1

To achieve expected result, use below option of using class name and event

  1. Pass $event and cat object to second loop click event
  2. Using event.target.className, update cat Object

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

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  title = "CodeSandbox";
  displayCat = "";
  services = [
    {
      cats: [{ name: "1aaa1", quantity: 10 }, { name: "1aaa2", quantity: 10 }]
    },
    {
      cats: [{ name: "2aaa1", quantity: 20 }, { name: "2aaa2", quantity: 20 }]
    }
  ];
  

  test(event, cat) {
    if (event.target.className === "increase") {
      cat.quantity++;
    }

    if (event.target.className === "decrease") {
      cat.quantity--;
    }

    if (event.target.className === "cat") {
      this.displayCat = cat.name;
    }
  }
}
<div *ngFor="let service of services">
  <div
    *ngFor="let cat of service.cats"
    class="main"
    (click)="test($event, cat)"
  >
    <div class="cat">{{cat.name}}</div>
    <div>{{cat.quantity}}</div>
    <div class="increase">+</div>
    <div class="decrease">-</div>
  </div>
</div>

Display Cat Name:
<div>{{displayCat}}</div>

codesandbox - https://codesandbox.io/s/20zzjqzm3n

Sign up to request clarification or add additional context in comments.

Comments

1

You could put some HTML attributes on the elements. In template

<div (click)="onClick($event)">
  <button *ngFor="let btn of buttons; let i = index"
     [attr.data-name]="btn" [attr.data-index]="i">
     {{btn}}
  </button>
</div>

and in TS

  onClick(event) {
    console.log(event.target.dataset.name, event.target.dataset.index);
  }

https://stackblitz.com/edit/angular-plfldc

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.