For every inner child elements you might need pointer-events:none; otherwise you may think you clicking inside .box but event.target is childnode like href..
@PimiTreeАй бұрын
Your right, this is the reason wht do event delegation almost usless
@ekchills69482 ай бұрын
I've become more confident in web development just watching your videos kyle
@jfftck2 ай бұрын
This technique is also useful for making the click outside of the modal dialogs close the dialog. You look for click events on the document and then use event.stopPropagation() on the dialog to prevent the dialog from closing, what will happen is the event starts at the top element under the cursor and then will bubble that event up to each parent until the event.stopPropagation() is called or it reaches the document root. The best way to use this in a framework, is to have a component that contains the dialog and add/removes the event from the document root and also applies the event.stopPropagation() to a click event on the dialog. This results in not having to track anything globally or on parent components. Just thought I’d share an example of how this is useful in a project.
@nagyszabolcs94512 ай бұрын
Going into the video, I actually thought he would mention this lol. Thanks for mentioning it here!
@dgdev69Ай бұрын
Thanks Kyle. I have been following you part of my software development journey past 2.5 years . You are always concise well structured.
@psycotrompus2 ай бұрын
My brain was flooded with different use cases after watching this. Great stuff!🤟
@davi485962 ай бұрын
5:01 Event Delegation timestamp
@shgysk8zer02 ай бұрын
I rarely use event delegation. While i know this is just a quick video on the concept, it does mask the problems and complexity and trade-offs. Suppose you have a button with an SVG or basically any child. There are different phases of an event and how it propagates, but the important thing here is that it could be the child element dispatching the click event, not the button itself. In some cases, it may be better to use `e.target.closest()` that'd match either the element or any parent element... But that just ends up being a trade-off between CPU usage and memory. You're saving a little bit of memory but adding extra computation time to the handler of every click event, even if it isn't the intended target. Personally, i prefer to generally avoid event delegation except when you want a whole bunch of children of a specific container to all call a certain function. Otherwise, I'd target just the desired elements or use a MutationObserver.
@dkznikolaj70132 ай бұрын
How much longer are we talking? Developers have a bad habit of looking at something that takes 200 milliseconds extra and then decide its an unreasonable tradeoff, in places where no one except for a robot would be able to notice it. Obviously with loops this is different, but even then you need some pretty big loops for it to matter to a human
@shgysk8zer02 ай бұрын
@@dkznikolaj7013 time varies, obviously. Any single instance will take far longer on lesser hardware, especially if there's a CPU intensive task running. Also could be affected by how deeply nested the target element is. But sometimes more importantly, they'll run for every one of those events for the lifetime of the document (or until removed). You also can't remove the event listeners without using something like a `map` because it won't be the callback actually used in the listener, even if you're using a named function. Where do you get the idea that 200ms is short? Ever tried scrolling on a page with such a delay in a scroll listener? Or trying to fill out a form with such an input listener. Heck, even just a click would noticeably feel sluggish. And I'd give you a frame rate of 5! That, Vs having listeners on the target elements themselves, taking up only a little RAM. Even if we're only talking about 1ms here, it's still a trade-off, and one where the CPU usage is wasteful and can really accumulate over time. Plus, computation means power consumption, but RAM does not. So which is the better approach is a trade-off, and which is better depends on various factors.
@adambickford87202 ай бұрын
@@dkznikolaj7013 It IS in a loop, the event loop! And its throwing a mind boggling number of events. 200ms is an eternity in UI
@maelstrom572 ай бұрын
Imagine being the kinda dev that considers CPU usage when writing JS.
@SebastianZartner2 ай бұрын
I was also going to note this. If you are oing with `e.target.closest()`, you should also pass the matched element to the callback function to avoid having to call it twice. And regarding CPU usage, this is really neglectable. Even on slow systems, `.closest()` is not even taking a microsecond to execute in most cases. You may try it yourself by wrapping it into `const s = performance.now()` and `console.log(performance.now() - s)`.
@crim-son2 ай бұрын
Nice tutorial, but you're screwed if the target element has nested children, you then now have to be checking with ". closest(...), .querySelector(...)" before you can carry out your actions, this works if the element you're targeting doesn't have much nestedchildren
@JohnDoe-rk7ex2 ай бұрын
Or using "includes" on the parent
@seanwilliams88332 ай бұрын
OMG this is so timely. I have a an employee directory and when I click on an employee card, a modal pops up. However, when I load new employee cards with AJAX, the modal wouldn't work. Now I know why!!! Forever indebted for this video! Spoke too soon - didn't work in my application for some reason.
@leo8482 ай бұрын
You should really try out a framework like Svelte or Vue, makes something like this completely impossible
@davidlacroix98372 ай бұрын
lol
@EricFressange2 ай бұрын
Thank you for this example. I was looking for how to do it in vanilla JS. It was very easy to do delegate with jQuery. I see just a little issue with your code : the event won't trigger if there is another element inside. You need to adjust your code to match also with the parents
@S_sword2 ай бұрын
Using the event listeners at the whole document may not be the best idea.... Instead, wrap the elements and add the listener to the parent... If you added it to the document, it will call the listener every time which slows the page down,however, adding the mousemove listener to the document might be a good idea if you need to use the cursor's position for something..
@luquillasnano2 ай бұрын
This is such a neat explanation. Thanks, hopefully I'm gonna make use of it right now.
@Georgggg2 ай бұрын
You can safely ditch this practice, it doesn't add any value, but add indirection with DOM events, which is painful to debug. When your events stop working due to some element inside boxes, or stopPropagation somewhere.. good luck.
@yomajo2 ай бұрын
Python "web" flask dev, working on second project. I used to attach event listeners on newly added elements. Will try this method next time situation presents itself. Thank you!
@moritzfinke45183 күн бұрын
Thank you for the video, it was really helpful.
@lesalmin2 ай бұрын
Just by watching this one tutorial video and learning everything done in it, you can already create the most important tasks of a beginner javascript coder.
@fiatlux8052 ай бұрын
I feel like a tiny flower learning to code (self taught) and your videos are like tidal waves lol. Great content, you deserve every like and every sub.
@AllinOne-ly4xi2 ай бұрын
Thank you sir i am stuck on this problem for many days now i understand how it works 👍👍
@isaidstream45472 ай бұрын
Not knowing what is a Event Delegation is the reason why I Ieft javascript 5 years ago, and all related to programming. Now i can do a proper To-do app and more... This css property has help me too: pointer-event: none
@ModSlash2 ай бұрын
Your videos are awesome, I often point them out to beginners touching on topics that they could use some help to get to grips with. Well done, and keep them coming. For this specific one, I know where you are coming from but this technically is not delegation :) In an older school of programmers that I am part of, this is iteration :)
@kazmuz5916Ай бұрын
Super helpful, thanks!
@MatthewNicholsDevGuy2 ай бұрын
Thanks, I didn't know about the .matches method. Good content as always.
@MrRagday2 ай бұрын
Thank you. From this example I understand that component approach >>> event delegation ;)
@isti19862 ай бұрын
It works as long as you dont have complex objects that you want to delegate your events to. In real live applications this unfortunately tend not to work, because e.target will be one of the internal elements within the 'box'.
@moofymoo2 ай бұрын
e.target.closest('.box') will find box element from box element or it's children. null if not clicked in box.
@isti19862 ай бұрын
@@moofymoo That's a good answer but not perfect. If you have other elements in your box, and any calling the event.stopPropagation() method, then your little event listener will never fire. Good luck figuring out in a larger code base when sometimes clicking on the box works and somethimes it doesnt. I think this is an error prone solution, I personally would not use it.
@reactoranime2 ай бұрын
pointer-events:none
@josuedelossantos94422 ай бұрын
Thank you, though I haven't used vanilla JS for a while.
@sinvalfelisberto2 ай бұрын
Perfect! Thank you!
@yashkhatri20992 ай бұрын
8:33 A simple correction: Actually we don't need parent argument. We can just pass '.grid .box' in parameter to select boxes only inside the grid element.
@lann1sterroy2 ай бұрын
I was studying event delegations 1-2 hour ago and Kyle dropped this video. Am i dreaming or something :))
@olamidehamed2 ай бұрын
My best tutor 🎉
@abhishek_236852 ай бұрын
One suggestion - You can move your camera a further back and then zoom in. That will give a natural camera view. Currently it feels like your face is directly on the screen, like you are trying get in to the camera as close as possible, which makes it bit weird to look at.
@chinmayghule82722 ай бұрын
Nice to see a noob level video after a long time. I started from those same videos. I feel like currently the channel lacks content for junior devs who're a little bit experienced. For example, if you're trying to create a whatsapp clone using MERN, then how are you going to design the database? What different collections will you use? What I mean is that things like planning a project and knowing how to create an architecture is something that can teach us a lot. I hope I get to see such a project done in one of these videos.
@wntiv2 ай бұрын
probly want to use .closest() instead of .matches() if your boxes have any children, so that clicking any of the children within the box will still activate the box itself (if that's what you want)
@alirezajafari53822 ай бұрын
this is amazing thank you so much❤❤
@DerPipo2 ай бұрын
This looks and feels like a good old web dev simplified video. ❤ Was this left over?
@anothermouth70772 ай бұрын
Such a neat technique!
@JoyfulDarts-fy4gc2 ай бұрын
Great explanation, as always on this channel
@Pluvo2for12 ай бұрын
This reminds me of event bubbling. Could we have a video on that please?
@RomanWeisman3 күн бұрын
Thanks.
@Vptechvelly2 ай бұрын
Kyle best tutor ever.🎉
@freerider34342 ай бұрын
Cool stuff, thx! Why bobblehead?
@frankoppongkonadu66762 ай бұрын
Well explained, Thank you boss
@TheSpr0gz2 ай бұрын
Good introductory video on event delegation. It would have been good to cover what happens if the .box has descendents of its own (img, span, etc.) and how to use e.target.closest('.box') to match the .box you want to toggle the class on because this happens a lot in the real world. Head up, at 3:36 (and another place somewhere in the video) you say, "taking an event that happened at a parent such as our document and we're delegating it down to one of the children". This is the wrong way around. You are actually delegating the handling of those child events to a parent you're not delegating anything to the children. Also, technically of course you're delegating a descendent element's events to an ancestor, not necessarily a child / parent relationship.
@AlThePal782 ай бұрын
Yo thius video is amazing I need this type of learning :)
@MarcosRVNeves22 күн бұрын
Couldn't I just use '.parent > .child' or '#parent > .child' if they are unique, instead of creating a fourth parameter in the event listener to pass the parent element? If you're adding an event listener to a very specific element or parent, you should consider using an id anyway. Additionally, you could use ':not(.parent) > .child' to select all child elements that are not part of the parent. That being said, good video, well explained.
@devwithbrian15342 ай бұрын
Thanks Kyle
@luisenriquecaleroanchelia63692 ай бұрын
Excelente video , saludos desde Perú 💪
@darkwater2342 ай бұрын
This is great! Well done!
@HeyNoah2 ай бұрын
Fantastic! Thank you!
@tarek-n3g2 ай бұрын
really helpful thanks bro !!
@zool2019752 ай бұрын
Only problem here is when you click on any child elements inside the boxes the expected behaviour will not trigger. Use *e.target.closest(".box")* to figure out if you clicked on any of the boxes and/or its child elements. *e.target.closest(".box")* will iterate trough itself and its parents till the query is met. if not so then it results with a NULL.
@kierrboy86132 ай бұрын
This is good
@petrmezera13962 ай бұрын
Is better use eventListener on "document" or on a "window"?
@StephanHaewss2 ай бұрын
Very nicely explained!
@cyberprompt2 ай бұрын
Knocked it out the box, Kyle.
@reddevils74242 ай бұрын
is there a more sufficient way to achieve the same thing with jquery?
@GonzaloMassa2 ай бұрын
jQuery includes that behavior out of the box. Just pass an extra argument with the selector to match, like in this example would be $(document).on('click', ((your event handler)), '.box');
@strategistaow35202 ай бұрын
People say that you shouldn't make lots of event listeners It's better to make just one listener for document and listen for e.target
@tweetoryt2 ай бұрын
Maybe add one example of how to handle the classic "icon on a button" scenario
@bytebytego-12 ай бұрын
Why is event bubbling is not seen here , as when we click on .box means we click the document too..
@irlshrek2 ай бұрын
Good question! It is actually happening. you are clicking on the element and then it bubbles up to the document where hes handling the bubbled-up event. That event still has as it's target the element that 'captured' the event before bubbling it up to document. This is actually a tiny bit inefficient but it works.
@KyrylWins2 ай бұрын
1.6 mil soon, keep going!
@StellarWeb0082 ай бұрын
Its weird to debug because if you have an element & want to check it's event listeners from the Elements tab, you can't do that because you would have to check events of each & every parent as you don't know which one might be delegating the event to it
@loic.bertrand2 ай бұрын
If we had child elements inside the boxes, wouldn't we need to use if (e.target.closest(selector) ) { ... } ? So it bubbles to the parent if we click a child element
@feesectiontsdps63912 ай бұрын
Superb
@evilmanua2 ай бұрын
mate, can you continue the event listeners topic, specifically removing event listeners?
@estebanfelipe39802 ай бұрын
I don't think the "matches" method you used would work if, for example, you had a paragraph inside each box and your clicked such paragraph, because the target would've been the paragraph, not the box, so the event wouldn't have triggered.
@TheSpr0gz2 ай бұрын
I was hoping Kyle would cover this case as it happens a lot in the real world. For that situation you would use e.target.closest('.box') which searches the DOM tree from e.target (inclusive) up the DOM tree and returns the first .box element it finds, or null if the clicked element wasn't a descendent of a .box element.
@starjuda3632 ай бұрын
thanks kyle
@JE-cp6zv2 ай бұрын
What’s the best way to reach you , I need help with mirroring a website that has javascript I’m able to get it downloaded locally but it won’t run the JavaScript. I would greatly appreciate any assistance. Thanks 🙂
@dynamohack2 ай бұрын
better when create element with onclick attribute and pass js function in it with dynamic arguments and it dont even require to add a single event listener
@d.sherman8563Ай бұрын
What do you think setting the onclick attribute does?
@dynamohackАй бұрын
@@d.sherman8563 onclick is a attribute which runs js written in onclick attribute either code or some functions in js which present on the document
@saefulrahman34782 ай бұрын
thanks bro, 👍
@karimkrimou3992 ай бұрын
Great video kyle bro
@abundiko2 ай бұрын
I've always rerun the loop and added all even listeners over again in the past. Thanks for the helpful content!
@ChrisAthanas2 ай бұрын
Both ways have advantages and trade offs I can see cases where one or the other approach is helpful
@StiekemeHenk2 ай бұрын
The original approach is better. Just add the listener you need when you create the item. Instead of running x listeners and x checks. One listener, no checks needed. You can easily remove code duplication with a function.
@froozenalex2 ай бұрын
Fr, the video has a pretty bad example of the problem
@chudchadanstud2 ай бұрын
Doesn't your method break encapsulation? Also your state is now scattered everywhere. If I make a change I'm now not aware of the effects.
@sergewert25602 ай бұрын
What if we replace parent parameter with right selector?
@evalaviniabucur17892 ай бұрын
You can do that: sending a selector for the parent. Then you'd need to do something like: document.querySelector(parentSelector).addEventListener(type, e => { if (!e.target.matches(selector)) return callback(e) })
@CarlMiller-p5o2 ай бұрын
🤯 - mind blowing
@davadh2 ай бұрын
Super useful
@todd.mitchell2 ай бұрын
Brilliant now I don't have to remove/add listeners every time my virtual scroll renders
@MrRagday2 ай бұрын
Why your components dont do it for you?
@todd.mitchell2 ай бұрын
@MrRagday I'm not using a component just plain vanilla JS.
@MrRagday2 ай бұрын
@@todd.mitchell component is an approach, not an entity.
@todd.mitchell2 ай бұрын
@MrRagday I meant I'm not using a component of a major framework. I wrote my own virtual scroll component using intersection observers. Unless you delegate the events you have to remove/add each one when re-rendering the scroll box. After watching this video I implemented this approach and love how elegant it is. Another commenter warned about using CSS class for logic. Valid concern. I could use the dataset but I understand navigating the DOM by class is more efficient than parsing the dataset; that ship has already sailed in my code. Plus I avoid the many remove/adds, speeding up the virtual scroll. I'm just going to document the design decision.
@lilbahr2 ай бұрын
I don't mean to be... uh mean or anything. Is that shake of your head a usual thing or is something the matter? I just realized, is ... that a thing? Maybe I am just noticing something nonissue. Maybe is just a way for the memory to work with explaining the issue. :) I love your videos. I just got to thinking...
@oumardicko55932 ай бұрын
Kinda nice, Not sure if this is gonna help our new front-end framework only developers xD
@nhutdev2 ай бұрын
Why can't I find the remove class "clicked" event?
@studytime80782 ай бұрын
Can’t we just set attribute (class) in box , to execute event listener
@Niksorus2 ай бұрын
Typically, that's where I'd make a separate component. A Web Component maybe if you really want no JS framework.
@MrRagday2 ай бұрын
Just simple function/class would be enough
@zeroc72532 ай бұрын
If box is nested with other elements, how do you get the desired click element?
@borstenpinsel2 ай бұрын
The element that was clicked is always known. Nested or not. But every element above it was also clicked and this is where the delegation (or often called bubbling up) comes into play. If you click any element on a website, you also clicked the body. That's rather obvious. But you also clicked every element of the nest as well. And every element gives this event to its parent. Unless you prevent it from doing so.
@zeroc72532 ай бұрын
@@borstenpinsel for example: Document .box{ display: flex; gap: 20px; } .tag{ width: 200px; height: 200px; background: skyblue; } .one{ width: 150px; height: 150px; background: orangered; } .two { width: 100px; height: 100px; background-color: #fff; color: #000; } .span { display: inline-flex; padding: 10px; border: 1px solid #000; } Tag1 Tag2 const box = document.querySelector(".box") box.addEventListener("click", event => { console.log("->> ", event.target) if(event.target.matches(".tag")){ console.log(event.target) } }) I mean, in a lot of development scenarios where elements are nested, like in this example, and you want to get the data-tag, you can't get it by clicking on one, two, and span. So you're looking for the parent element to match。
@zeroc72532 ай бұрын
@@borstenpinselfor example: Document .box { display: flex; gap: 20px; } .tag { width: 200px; height: 200px; background: skyblue; } .one { width: 150px; height: 150px; background: orangered; } .two { width: 100px; height: 100px; background-color: #fff; color: #000; } .span { display: inline-flex; padding: 10px; border: 1px solid #000; } Tag1 Tag2 const box = document.querySelector(".box") box.addEventListener("click", event => { console.log("->> ", event.target) if (event.target.matches(".tag")) { console.log(event.target) } }) delegationEvent(box, (event, dataValue)=>{ console.log("find: ", dataValue) }, "div", "data-tag") function delegationEvent(proxy, handleFunc, matchEl, attrName) { proxy.addEventListener("click", (event) => { let target = event.target; while (target !== proxy) { if (matchEl && attrName) { let attrVal = matchDOM(target, matchEl, attrName) if (attrVal !== null) { return handleFunc(target, attrVal) } } target = target.parentNode } }) } function matchDOM(target, matchEl, attrName) { if (matchEl && attrName) { let attrVal = target.getAttribute(attrName) if (target.nodeName.toUpperCase() === matchEl.toUpperCase() && attrVal != null) { return attrVal } } return null } I mean, in a lot of development scenarios where elements are nested, like in this example, and you want to get the data-tag, you can't get it by clicking on one, two, and span. So you're looking for the parent element to match. I wrote a function that is more in line with the development scenario, so that whatever element is clicked under the proxy will get the desired object.
@skeleton_craftGaming2 ай бұрын
Jquery solved this a long time ago, there is no reason for using raw JavaScript to do this in a web setting
@OCEMTechZone2 ай бұрын
Great
@TomasMisura2 ай бұрын
i use event delegation as much as possible. But i do not overuse it ...
@keremardicli40132 ай бұрын
Next video: Event propagation in 10 mins
@EricSundquistKC2 ай бұрын
I'm dying for you to update your VS Code! 😭
@uplink-on-yt2 ай бұрын
jQuery did that selector trick back when it was cool.
@aram56422 ай бұрын
The more serious problem that delegation solves is when you remove boxes. It frees you from removing individual event listeners for which a reference you'd have to store
@torquebiker99592 ай бұрын
When you remove boxes from the DOM, their event listeners are also removed, no?
@TheGryphon142 ай бұрын
no, garbage collector handles that for you
@TheSpr0gz2 ай бұрын
@@torquebiker9959 Garbage collection will clean up, provided there are no other references to the event listener function or the DOM element.
@MrRagday2 ай бұрын
@@torquebiker9959 no. It will be removed if nothing will point to box from global/running code. Not only dom but some vaiables/properties too.
@veenitchauhan61312 ай бұрын
Exelent
@paxdriver2 ай бұрын
Correction: "linearly" adds more complexity, not "exponentially" Sorry... It's not you, it's me lol
@MrLinuxFreakАй бұрын
Or an more easy way is to just bind the function on box creation instead of listening and searching the whole doom every click..
@BurritoBrooks2 ай бұрын
🔥🔥🔥
@jasonsworld3332 ай бұрын
Why for non existent jobs?
@NaifIT112 ай бұрын
I love DOM and native thing i dont know i hate js frameworks😂
@MrRagday2 ай бұрын
Dont use frameworks . Use react-js instead
@felippealmeida80752 ай бұрын
thats nice, but i believe its not necessary if u are using react, since event delegation will be on each react component definition, right?
@richardrosalesmaldonado82292 ай бұрын
Es una mala práctica usar eventos del javascript cuando usas React, Angular, etc. Esto es para cuando unas vanilla js
@ukyo61952 ай бұрын
Frickeling in react is not web developing
@ChandrashekarCN2 ай бұрын
💖💖💖💖
@moofymoo2 ай бұрын
Hello jQuery development patterns! nice to see how upset some modern framework people are in comment section :D
@MrRagday2 ай бұрын
Modern frameworks also can use this pattern
@injSrc2 ай бұрын
In this scenario adding the event listener right when it was created would have been a sensible solution too
@evalaviniabucur17892 ай бұрын
I actually think it would still have been a horrible idea, as you could have a thousand such boxes and then a thousand such event listeners would have been added - which seems far from ideal.
@MrRagday2 ай бұрын
@@evalaviniabucur1789 actually its great idea. If you also encapsulate box and listener in some function or clas you'll get so-called component. Which used in 99% of web apps. And only if your users really create thousands of boxes and they are upset about perfomance drop you'll think how to fix it with smth like event delegation.
@АнтонВоронов-ы9ц2 ай бұрын
3:20 Code that delays work on those elements that are not used. Also, this code complicates debugging and finding errors. I have seen such code in real projects several times, which was one of the signs of low-quality code.
@StiekemeHenk2 ай бұрын
This sounds terrible. Click once, trigger hundreds of checks or eventlisteners. Instead you could just make a proper function to remove the code duplication and have one click, one event, zero checks.
@abhishek_4222 ай бұрын
why he shakes his head so much, I am an indian I we are known for the head gestures but he is on next level 😂