0

I have gradually migrated my app from straight MVC4 to using a lot more ajax and dynamically loaded partial views. I like it, but in the process my javascript and event management have gotten a bit unweildy so I'm trying to get it more organized and maintainable. One of the things I keep tripping up on is loading events for elements that don't exist in the dom yet.

Using delegated events as described in this thread: how-should-javascript-in-an-ajax-loaded-partial-view-be-handled looks like it would help me out a lot, but I can't get it to work.

I have the following on main page load (not a partial view). In this example #maincontainer exists on page load and throughout the execution of the application. ".panetitle" is loaded later via a partial view. When it is visible, $("#maincontainer .panetitle") in devtools locates it fine. There's no other event handling involving #maincontainer

$(document).ready(function () {
    $('#maincontainer').on('click', '.panetitle', function () {
        console.log('clicked');           
    });
});

My understanding of this form of .on() is that #maincontainer needs to exist when the page is loaded, but the event should be in effect for '.panetitle' descendants of #maincontainer whenever they appear in the future. 1) Is my understanding correct? 2) Am I using it correctly? 3) Any suggestions? :)

As always, thanks. Joel

Community
  • 1
  • 1
Joel
  • 647
  • 2
  • 11
  • 22

2 Answers2

2

From what you've described, it appears that you are using it correctly. Here are some things to check:

  1. #maincontainer must exist at the time you install the event handler.
  2. #maincontainer must be a parent of .panetitle.
  3. #maincontainer must not be destroyed and recreated unless you reinstall the event handler.
  4. .panetitle and its parents must be allowing event propagation so no intervening event handlers can be stopping event propagation up to #maincontainer.
  5. .panetitle itself must be receiving the click event so it can propagate it (the click isn't blocked or taken by any other object).
  6. The .panetitle object must have that class name at the time of the click.

You can check to see if 1, 2 or 3 are an issue by trying this as a debug step (not generally recommended to put all delegated events on the document as they should be located as close to the dynamic object as possible for better performance in large applications):

$(document).ready(function () {
    $(document).on('click', '.panetitle', function () {
        console.log('clicked');           
    });
});

If that isn't working either, then it's probably 4, 5 or 6 or something else we haven't yet dreamed up. You can try this as a debug step:

$(document).ready(function () {
    $(document).on('click', function (e) {
        var t = e.target;
        console.log('click: tag = ' + t.tagName + ", class = " + t.className);           
    });
});

With this debug handler installed, click on the .panetitle object and see what you see in the debug console at that exact moment. Are you getting any click event? Is it for a different object? If even then you're getting no click event, then something must be blocking propagation. If you're getting the event, but for a different object, then something must be on top of .panetitle.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Added several more possibilities and debugging steps. – jfriend00 Nov 16 '13 at 21:46
  • thanks for the suggestions. I think I need to rule out #4 and #5. Thanks for the debugging tip too. – Joel Nov 16 '13 at 21:49
  • I think the event is getting blocked by something else. I didn't consider that at first because I've been handling events on this element, but at a different point in the flow. This is a perfect example of why I need to change my event handling methodology. It's gotten away from me. :) – Joel Nov 16 '13 at 22:55
  • specifically, I had some event handling for a surrounding div that contained a "return false" where a simple "return" would have sufficed. – Joel Nov 16 '13 at 23:52
  • @Joel - yep, that will do it. In a jQuery event handler, `return false` will do both `stopPropagation()` and `preventDefault()`. – jfriend00 Nov 17 '13 at 00:09
0

try this instead:

$(document).ready(function () {
    $(document).on('click', '.panetitle', function () {
        console.log('clicked');           
    });
});
Alessandro Minoccheri
  • 35,521
  • 22
  • 122
  • 171
  • Thanks Alessandro. That didn't work, (for reasons I describe below) but it was a good troubleshooting tip. – Joel Nov 16 '13 at 23:53