how to get the element holding the event listener (ng-click) ?

4,687 views
Skip to first unread message

Olivier Percebois-Garve

unread,
Jan 22, 2014, 9:59:58 AM1/22/14
to ang...@googlegroups.com
Hi all,

when passing the $event object, the targeted element is available but not the "listening" element :

<div ng-click="foo($event)"> <span>bla bla</span></div>

--> click on "bla bla"

$event contains :
  1. targetspan
  2. srcElementspan

  3. toElementspan
 
But I couldn't figure out any way to get the div. Passing "this" doesn't work, I get something ressembling the current scope.

Is there any way to get that listening element ?

thanks

-Olivvv



Sander Elias

unread,
Jan 22, 2014, 10:17:26 AM1/22/14
to ang...@googlegroups.com
Hi Olivier,

Did you examine the event in your debugger?
Angular events are dressed up dom events, have a look at the documentation on click events.
you need $event.currentTarget.

Regards
Sander

Olivier Percebois-Garve

unread,
Jan 22, 2014, 10:25:32 AM1/22/14
to ang...@googlegroups.com
Hi Sander,

thanks for help. currentTarget comes out with the value null. 

I have that in a plunkr : http://plnkr.co/edit/zbDjT3?p=preview 

(click on the stuff with the red border, then on a list element. The first li contains spans, if those are clicked, no way to get the li)

-olivvv



--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/groups/opt_out.

Sander Elias

unread,
Jan 22, 2014, 10:57:22 AM1/22/14
to ang...@googlegroups.com
Hi Olivier,

You are right, if you click on an element, that you removed from the dom, then added, then removed again, and then added again, somehow the browser lost track of its parent! 
I'm not sure where to even begin on this one! I'm not even sure if it's an angular or a browser issue.

Regards
Sander

Olivier Percebois-Garve

unread,
Jan 22, 2014, 11:04:44 AM1/22/14
to ang...@googlegroups.com
Hi Sander,

I do not know where you see this. 

The replacement of elements occurs only during the loading of the directive.
There is no such behavior when you click on one of the list element.

As for the replacement itself, the string is built manually and then goes through :
var out = $compile(out)($scope);
Is there something missing there ? is it not legit ?

This is happening only once, during the loading of the directive. But there is no remove, add, remove, add.
I added a log to prove that : http://plnkr.co/edit/1G8dUy?p=preview

-olivier




Sander Elias

unread,
Jan 22, 2014, 11:54:44 AM1/22/14
to ang...@googlegroups.com
Hi Olivier,

You are right, it is just taken out once, and then put back in.
I didn't scan your code carefully enough. After using the tidy-up button it became more apparent! 
Will go over it once more, and let you know. Probably not today anymore!

Regards
Sander

Olivier Percebois-Garve

unread,
Jan 22, 2014, 12:09:57 PM1/22/14
to ang...@googlegroups.com
I know you are doing a tremendous work helping people.
On thisone you made me really fear I produced some pointless code.

But ok there was some legacy stuff in the plunkr, so it was hard to get through for you.
So I did a cleanup of all useless stuff, and tada it works.

I proves that when facing some weird result, it makes sense to first remove all the weird stuff arround it.

Thanks for all Sander, nice evening !


-olivier 


Sander Elias

unread,
Jan 22, 2014, 12:13:28 PM1/22/14
to ang...@googlegroups.com
Hi Olivier,

Thanks for the update. I was indeed thrown off by all the cruft. Apparently so was the browser/angular ;)

Regards
Sander

Sander Elias

unread,
Jan 22, 2014, 12:14:49 PM1/22/14
to ang...@googlegroups.com
Oh, do you mind sharing your working plunk? perhaps its of use for anybody else!

Olivier Percebois-Garve

unread,
Jan 22, 2014, 12:18:42 PM1/22/14
to ang...@googlegroups.com
Sure http://plnkr.co/edit/VgGVJO?p=preview

its even annoted for you pointing to the bug that doesn't exist anymore ;).

I'd love comment about the coding style though and my crimes against the angularish aesthetics... 


--

Sander Elias

unread,
Jan 22, 2014, 1:25:37 PM1/22/14
to ang...@googlegroups.com
Hi Olivier,

I don't have the steam to work it out now,  But why did you do the entire construct like that it looks overly complicated and fragile to me?
Don't see a reason for the transclude. 
How about splitting it in 2?
  1 dropdown directive, that hold the logic for the list, and the entry-point.
  2. a couple of dropdown-item directives, that handles their own, and require the dropdown to register there?

Regards
Sander

 

Olivier Percebois-Garve

unread,
Jan 22, 2014, 2:06:22 PM1/22/14
to ang...@googlegroups.com
Hi Sander,

If you need to rest please do it.... we can continue this conversation another day.

The reason for the transclude is the replaceWith of the base element of the directive. The directive replace the custom element <dropdown> with valid markup.
I thought that was pretty the point of angularjs, i.e the ability to extend html.

I dont know how to split that in 2, I never made directives that communicate with each other, and also I did not get to read about it.


at this stage the purpose of this directive is rather simple. It is a replacement for the html element <select>. The only additional feature compared to a <select> is that it can have html with the <option> element instead of text. Later I will add more features, like a search field.

So now, I think the logic in it can be simply described. There is 2 parts :
1. translate the custom markup to valid markup.
2. handle interactivity (show/hide of the options and click-to-select)

I guess the stuff that feels weird to you are rather located in the part 1:

a.
The attributesToString() function is used to copy the attributes of the original element <dropdown> to the replacement element, a <span>. I did not knew any angularjs prescription about this, but I thought it would be nice if the directive let developer that use it add their attributes if they need to, for whatever reasons.

b.
The angular.forEach loop copies the <option> contents and values to a <li> collection and sets the default value in the top <span>.

c.
Stuff mades in steps (a) and (b) are populated into the html structure, and then compiled with $compile to give angular knowledge of the event handlers in it.

part 2:
just 2 methods show() and select() to respectively show the list and select an item in it.


What  are the parts that appear to you as fragile ?


-olivier



 



















--

Sander Elias

unread,
Jan 23, 2014, 12:21:29 AM1/23/14
to ang...@googlegroups.com

Hi Olivier,

I will go over your reply and answer inline.

The reason for the transclude is the replaceWith of the base element of the directive. The directive replace the custom element <dropdown> with valid markup.
I thought that was pretty the point of angularjs, i.e the ability to extend html.

Euhm, yes, one of the points is extending HTML. However, what’s the use of replacing HTML with so called ‘valid HTML’? Who is validating? And when? Are you going to run a HTML validator on your HTML after Angular is done with it?
If you want, you can write HTML that can be validated, but it takes extra effort. Personally I don’t see any added value there.

I dont know how to split that in 2, I never made directives that communicate with each other, and also I did not get to read about it.

Well, that’s not a excuse is it? ;)

at this stage the purpose of this directive is rather simple. It is a replacement for the html element <select>. The only additional feature compared to a <select> is that it can have html with the <option> element instead of text. Later I will add more features, like a search field.

So now, I think the logic in it can be simply described. There is 2 parts :
1. translate the custom markup to valid markup.
2. handle interactivity (show/hide of the options and click-to-select)

I guess the stuff that feels weird to you are rather located in the part 1:

a.
The attributesToString() function is used to copy the attributes of the original element <dropdown> to the replacement element, a <span>. I did not knew any angularjs prescription about this, but I thought it would be nice if the directive let developer that use it add their attributes if they need to, for whatever reasons.

b.
The angular.forEach loop copies the <option> contents and values to a <li> collection and sets the default value in the top <span>.

c.
Stuff mades in steps (a) and (b) are populated into the html structure, and then compiled with $compile to give angular knowledge of the event handlers in it.

part 2:
just 2 methods show() and select() to respectively show the list and select an item in it.


What  are the parts that appear to you as fragile ?

Well, where to start? You replaced dom manipulation with string manipulation. Although that is possible as you have shown, I don’t think it’s such a good idea.
Then you are using the DOM/HTML/Template as source where your data is coming from. Again possible, but it defeats the whole idea of angular!
Also you are trying to make the final result in the DOM is validatable HTML? Seems backward to me, and also if this is a demand, it’s failing at that too!

<ul ng-show="display" class="ng-scope ng-hide">`
   <li ng-click="select($event);" data-value="1"> <span class="bla">abc</span><span class="bli">def</span></li>
   <li ng-click="select($event);" data-value="2">xyz</li>
   <li ng-click="select($event);" data-value="3">foo</li>
   <li ng-click="select($event);" data-value="4">bar</li>
</ul>

That is what your code is producing as final result. Looks nice, but all the ng-xxx aren’t valid HTML. This is easily solved, but that’s not the point!

Let me know what your thoughts are now, and we will see how to proceed.
Regards
Sander

Sander Elias

unread,
Jan 23, 2014, 3:15:16 AM1/23/14
to ang...@googlegroups.com
Olivier,

Olivier Percebois-Garve

unread,
Jan 23, 2014, 3:43:12 AM1/23/14
to ang...@googlegroups.com
Wow, thanks a lot, looks great. The angular way. I am studying it now.


On Thu, Jan 23, 2014 at 9:15 AM, Sander Elias <sande...@gmail.com> wrote:
Olivier,

--

Olivier Percebois-Garve

unread,
Jan 23, 2014, 5:38:28 AM1/23/14
to ang...@googlegroups.com
Just a partial auto-response, for future reference.

currentTarget is null if Firefox is used.

To make sure it is cross-browser, this is what is needed:

var el = event.target || event.srcElement;

Olivier Percebois-Garve

unread,
Jan 23, 2014, 5:41:43 AM1/23/14
to ang...@googlegroups.com
hummm...

var el = $event.target || $event.srcElement;

Sander Elias

unread,
Jan 23, 2014, 7:26:09 AM1/23/14
to ang...@googlegroups.com
Hi Olivier,

It is almost the angular way. I stayed with your example, and did read the data out of the DOM. This is not a good idea, and can be done way more Angular!

Regards
Sander

Olivier Percebois-Garve

unread,
Jan 23, 2014, 7:42:17 AM1/23/14
to ang...@googlegroups.com
Hi Sander,

I am currently playing with it and trying to let my mind be changed, before to comment on it.
What would be a better way to read the data ? 
(The directive is meant to be used by other dev, I thought I would be nice to just have to tell them "code a normal select element, with only a few minor changes". That's the reason why I choose to make it read data from the dom )

-Olivier


--

Sander Elias

unread,
Jan 23, 2014, 8:15:18 AM1/23/14
to ang...@googlegroups.com

Olivier,

Put it in a array on the scope, and iterate.

in the controller:

  $scope.items = [
     {value : 1 , description : 'Hello darkness,'},
     {value : 2 , description : 'my old friend'},
     {value : 3 , description : 'I'v come to talk with you again.'},
     {value : 4 , description : 'Because a vision softly creeping'},
   ];

in template: <doptions ng-repeat='item in items' value='item.value>{{item.description}}</doptions>

Regards
Sander

Reply all
Reply to author
Forward
0 new messages