33

I know that we can attach events with the jQuery on() function and remove them again with off().

In an existing project I do sometimes come across code similar to this:

$("#SomeId").off("click").on("click");

or sometimes when using namespacing similar to this:

$("#SomeId").off("click.namespace").on("click.namespace"); 

As far as I know you can only attach a single event to a specific namespace of the event.

For example if I simply do on("click") it will attach my specified function, overwriting the current function assigned, adding to the "click" event.

If I do on("click.namespace") it will attach my specified function overwriting the current function assigned, adding to the click.namespace.

What is the point removing any events by chaining an off("click") to the on("click) if on() already replaces any functions assigned to the specified event/event.namespace?

Is it redundant syntax in our code or is there a reason for it which I have missed?

Edit - Thank you kapa
I feel a bit silly now, I corrected my faulty knowledge above. Executing on("click.namespace1") several times I observed now that the data("events") object kept adding to the click event array.

I think that answers my own question there. That is why one would use off("event.namespace") to ensure nothing else is attached to that exact event/event.namespace.

kapa
  • 77,694
  • 21
  • 158
  • 175
Jason
  • 397
  • 1
  • 3
  • 10

3 Answers3

46

Actually you can attach multiple event handlers to the same event, not just one. Even when namespaces are used. Check out this quick demo.

Actually, one advantage of namespaces is that you can mark a group of event handlers, and easily remove them later to avoid attaching them several times. This is what this line does:

$("#SomeId").off("click.namespace").on("click.namespace"); 
kapa
  • 77,694
  • 21
  • 158
  • 175
  • I edited my question with the new findings based on your feedback. I feel a bit silly I never noticed that before when observing the `data("events")` object. Thank you for your answer. – Jason Jun 11 '12 at 12:25
  • same as above fiddle added some comments Hope it will be helpful for some one https://jsfiddle.net/AnuragKumar/d4j30k1q/ – Anurag_BEHS Aug 27 '18 at 16:25
  • thank me later https://www.andismith.com/blogs/2013/02/jquery-on-and-off-namespacing/ – Kugan Kumar Mar 25 '20 at 16:22
3

You may want to try .one('click.namspace') instead of .on('click.namespace').

$('p')
  .off('click.namespace', clickCB)
  .one('click.namespace', clickCB); // note the .one() here

This way you ensure that the click is not called more than once, otherwise, the .on(...) will only keep adding click-event-handlers (clickCBs) to the click.namespace event on p element and will be called multiple times before the .off() is triggered.

Good Luck...

Aakash
  • 21,375
  • 7
  • 100
  • 81
  • Will this still keep adding the event handlers? `$("#SomeId").off("click.namespace").on("click.namespace"); ` – MR_AMDEV Jan 01 '21 at 22:32
  • i think that will clear them before adding new – MR_AMDEV Jan 01 '21 at 22:32
  • 1
    @MR_AMDEV, I can't recall the context where this solution helped me. If I recall; I'll add a code-snippet for the same. Thanks :) – Aakash Jan 02 '21 at 05:23
  • 1
    @MR_AMDEV It is important to note that it does not remove the event before adding new, but rather removes the event AFTER it has been executed – beer73 Feb 03 '23 at 18:26
0

If there is an existing hander (since you may have more than one, in this case, they will chain), and it calls .stopPropagation(), then your hander will not be called. Writing the code as above will avoid this issue.

Jay
  • 3,285
  • 1
  • 20
  • 19