简体   繁体   中英

jQuery - Reinitialize DOM listeners

i have a lot of jQuery Event listeners that initialize when the document finishes loading. that part is working fine. I have a function that makes ajax calls and gets responses as strings of HTML that I append with jQuery to parts of the DOM. Although the append works, THAT new HTML snippet of code doesn't work with the jQuery event listeners because it wasn't part of the DOM when it loaded. Is there a way to reinitialize jQuery event listeners?

Here is another thing: I tried to store the event listener(s) in a function (function a ) and call that function whenever I wanted the listeners reinitialized. That worked partially... Although the listeners responded to to new HTML snippets, the results of the listeners were doubled, and keeps doubling whenever function a() is called, resulting in a major bug.

I'm Mixing jQuery and Angular. Here is a snippet:

$(document).ready(function(){
     $('.like-btn').click(function(){

      var likeStatus = $(this).data('like-status-json');
      var contentType = $(this).data('content-type');
      var contentID = $(this).data('content-id');
      var likeMeter_id = '#' + contentType.toLowerCase() + '-' + 'likemeter' + '-' + contentID;
      var likeMeter_elm = $(likeMeter_id);

      // console.log( likeStatus, contentType, $(likeMeter_elm) );

      var obj = {
        likeStatus: likeStatus,
        contentType: contentType,
        contentID: contentID,
        likeMeter_elm: likeMeter_elm,
        likes: parseInt( $(likeMeter_elm).text() ),
        og_elm: $(this)
      }

      $scope.likeAction(obj);

    });
}); 

$scope.likeAction = function(dataObj) {
    // console.log(dataObj);

    var req = {
      method: 'POST',
      url: '/action/ajax/',
      headers: {
        'Content-Type': 'application/json',
        'responseType': 'json',
        "Accept" : "application/json",
        'X-CSRFToken': Cookies.get('csrftoken')
      },
      data: {
        action: dataObj.likeStatus.action,
        info: dataObj,
        csrfmiddlewaretoken: Cookies.get('csrftoken'),
      }
    }

    $http(req).then(function(resp){
      // Success Callback
      // console.log(resp);
      $(dataObj.og_elm).data('like-status-json', resp.data.likeStatus);
      $(dataObj.og_elm).removeClass(dataObj.likeStatus.class).addClass(resp.data.likeStatus.class);
      $(dataObj.og_elm).children('span.like-text').text(resp.data.likeStatus.text);
      $(dataObj.likeMeter_elm).text(resp.data.likeMeter);
    },
    function(resp){
      // Error Callback
      // console.log(resp);
    });
  }

Here is the ajax that appends new HTML snippets:

$scope.addPostCommentUser = function(inputELM, dataObj) {
    if( inputELM == undefined || dataObj == undefined ) {
      console.log('Missing Inputs...');
      return;
    }

    console.log(dataObj);
    // return;

    var req = {
      method: 'POST',
      url: '/action/ajax/',
      headers: {
        'Content-Type': 'application/json',
        'responseType': 'json',
        "Accept" : "application/json",
        'X-CSRFToken': Cookies.get('csrftoken')
      },
      data: {
        action: 'addPostCommentUser',
        info: dataObj,
        csrfmiddlewaretoken: Cookies.get('csrftoken'),
      }
    }

    $http(req).then(function(resp){
      // Success Callback
      console.log(resp);
      var id = '#cmlst-' + dataObj.post_id;
      $(id).append(resp.data.comment_html)
      $(inputELM).val('');


    },
    function(resp){
      // Error Callback
      console.log(resp);
    });
  }

You need to use the on -call, instead of click and others - that should solve it.

So instead of $('.like-btn').click(function() you would do $('.like-btn').on('click',function()

I'm not a 100% sure it will work with the mix of functions and Angular you have, but try it and see.

Attach the event to the parent element of the dynamically created elements using event delegation. See .on()

$("[id|=cmlst]")
.on("click"
, "css selector of element within `resp.data.comment_html` at `.then()`"
, clickHandlerFunctionReference);

i actually found my own way of solving this problem.

I created a functions that applies a jQuery event listener to the element(s) from the given arguments/input parameters. So whenever i get HTML strings from server-side AJAX, i use jQuery to create a new DOM element and pass it to that function! It works perfectly actually!!!

Here is the example:

$scope.applyNewLikeListeners = function(elm) {
    $(elm).find('.like-btn').on('click', function(){
      var likeStatus = $(this).data('like-status-json');
      var contentType = $(this).data('content-type');
      var contentID = $(this).data('content-id');
      var likeMeter_id = '#' + contentType.toLowerCase() + '-' + 'likemeter' + '-' + contentID;
      var likeMeter_elm = $(likeMeter_id);

      var obj = {
        likeStatus: likeStatus,
        contentType: contentType,
        contentID: contentID,
        likeMeter_elm: likeMeter_elm,
        likes: parseInt( $(likeMeter_elm).text() ),
        og_elm: $(this)
      }

      $scope.likeAction(obj);
    });
  }

It works!

$scope.addCommentReplyUser = function(inputELM, dataObj) {
    if( inputELM == undefined || dataObj == undefined ) {
      console.log('Missing Inputs...');
      return;
    }

    console.log(dataObj);
    // return;

    var req = {
      method: 'POST',
      url: '/action/ajax/',
      headers: {
        'Content-Type': 'application/json',
        'responseType': 'json',
        "Accept" : "application/json",
        'X-CSRFToken': Cookies.get('csrftoken')
      },
      data: {
        action: 'addCommentReplyUser',
        info: dataObj,
        csrfmiddlewaretoken: Cookies.get('csrftoken'),
      }
    }

    $http(req).then(function(resp){
      // Success Callback
      console.log(resp);
      var id = '#rplst-' + dataObj.comment_id;
      var elm = $(resp.data.reply_html)
      $(id).append(elm)
      $(inputELM).val('');
      $(dataObj.replyMeter_elm).text(resp.data.replyMeter);
      $scope.applyNewLikeListeners(elm);

    },
    function(resp){
      // Error Callback
      console.log(resp);
    });
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM