2

I have many items created via *ngFor :

 <my-item *ngFor="let item of myArray" [p]="item" > </my-item>

I can listen to a click event via

 <my-item ... (click)="doWork(item) > </my-item>

But I don't want to attach so many event handlers ( since I have many components on that ngFor).

I was wondering if I can attach an event handler to the window object(only once) ( via @HostListener) and then to analyze the target property of event and to get the actual Entity that was clicked on - but I had no success.

Question:

I've made this plunker which already listens to a window click .
But How can I get the actual reference to the item ( in *ngFor="let item of myArray") that was clicked ?

In other words :

export class App {
  myArray:Person[] = new Array<Person>();

  @HostListener("window:click", ['$event'])
   onWindowclick() {
   console.log('click') 
   // how can I get a reference to the currently clicked item (as a `Person` entity) ?

  }

Nb I prefer not to attach an Id and then to search that Id in an array

Royi Namir
  • 144,742
  • 138
  • 468
  • 792

2 Answers2

1

Handle it by using custom directive as below

import { Directive, HostListener, Renderer, ElementRef } from '@angular/core';
@Directive({
    selector: '[cicked]'
})
export class ClickDirective{

    constructor(
        private renderer: Renderer,
        private el: ElementRef
    ){}

    @HostListener('click') onClick() {
      this.el.nativeElement.attributes[..] // using this you handle handle the entity clicked
     console.log('some thing key upped')

    }
}

Use this line for your required parameter in the directive which is updated in demo

console.log(JSON.stringify(this.el.nativeElement.attributes['ng-reflect-p'].nodeValue));

LIVE DEMO

Aravind
  • 40,391
  • 16
  • 91
  • 110
  • I don't see how it relates to the question. Your code doesn't yield the clicked entity. – Royi Namir Apr 09 '17 at 17:07
  • [Did you see the output](https://i.imgur.com/YmJ6NN7.jpg) ? Also (again) i'm after the entity. Just like as `doWork( p: Person) { ... }` is getting the `Person` object. I want that entity – Royi Namir Apr 09 '17 at 17:16
  • you cannot have it as an object but you can have it as a string there. Also what is that you look to do when that entity is clicked. Instead you can use the component to handle them – Aravind Apr 09 '17 at 17:20
  • Even then - the string that you're returning is json with two empty objects. Not to mention that your directive also apply event handler to each item in the ngFor. ( which is exactly what I didn't want to do). Also why did you remove `[p]="item"` ? and placed `[p]="item.Name"` ? – Royi Namir Apr 09 '17 at 17:22
  • as I said earlier you cannot take a object and handle in your directive. This can be handled in the component itself instead of so much complications – Aravind Apr 09 '17 at 17:29
  • I don't understand. your plunker ( and I have the latest version , maybe you don't - open it in incognito) does not yield the components in the ngFor ( name,age ) also you've attached a event handler to each component which I didnt want to do . so your answer doesn't even keeping the current functionally. . Anyway thank you. – Royi Namir Apr 09 '17 at 17:34
  • see the last console.log and not the first empty object – Aravind Apr 09 '17 at 17:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/141292/discussion-between-aravind-and-royi). – Aravind Apr 09 '17 at 17:44
  • sorry my friend I was away (regarding chat invitation) – Royi Namir Apr 10 '17 at 05:33
0

I was playing around with your Plunkr and I honestly don't think this is possible (or intended to be) in Angular2.

Some hacky solutions that I thought would work:

Adding a display: none input text as a child element inside my-item with its [value] binding set to p: Person

This obviously didn't work, [value] bindings can only be string

Same as above but using a <\select> tag with [ngValue] binding on its first option This method would have preserved the full Person object however angular doesn't expose the value property to the DOM and therefore it cannot be accessed from a Window event.

Now, I'm hesitant to say its impossible - because I'm by no means an expert but I'd suggest just sticking to event handlers regardless.

There will be minimal overhead in adding an event handler to every item in your array.

Community
  • 1
  • 1
Daniel Cooke
  • 1,426
  • 12
  • 22