skip to Main Content

I know that I can fire functions after ajax call using the success option, e.g. to manipulate loaded content, like

$.ajax({
    url : url,
    ...
    success: function(data, textStatus, jqXHR){
        alert($('#overlay > #popup input').length);
    },
    ...
});

I also know that I can apply interactive events like click on ajax loaded content via

$(document).on('click','#overlay > #popup',function(e) {
    alert($(e.target).find('input').length);
});

which works ofcourse.

I try to find a way, do the same alert automatically, only after content has been loaded, instead of click on it, like this (sorry for this bad NON-working example)

$(document).on('load','#overlay > #popup',function(e) {
    alert($(e.target).find('input').length);
});

EXAMPLE for explaination, not part of the question

At the end I want to apply calculated styles to loaded input[type=radio] using jQuery (individual width, depending on its value attribute, to be displayed automatically in css pseudo element ::after {content: attr(value);} )

The current html output from php function is

<label class="fl" style="width: 80px;">
    <input type="radio" name="' . $name . '" value="' . $year . '" ' . ($year == date('Y')?'checked="checked"':'') . '/>
</label>

the current result looks like this

four styled input type radio

where the visible captions are the ::after elements. Only I want – in case of different value length – the width is set automatically, not hard coded.

Can somebody open this node in my head ?

2

Answers


  1. Chosen as BEST ANSWER

    SOLUTION based on @CertainPerformance 's answer

    $(document).on('ajaxComplete', function(e){
        var i = $('#overlay > #popup').find('input[type="radio"],input[type="checkbox"]');
        i.each(function(index){
            var el = $(this);
            var l = el.closest('label');
            var v = el.attr('value');
            var fs = el.css('font-size');
            $('body').prepend($('<span></span>').attr('id','st'+index).addClass('st').html(v).css({fontSize:fs}));
            var testel = $('body > span#st'+index);
            var w = testel.outerWidth();
            l.css({width:w+30}); /* +30 instead of a padding */
        });
        $('body > span.st').remove();
    });
    

    Works exactly as I want. And the entire thing saves ajax payload, as intended.

    An here's the result (with nonsense content, for demo only)

    input radio with nonsense content, for demo only


  2. If you know which element is going to be appended to on ajax complete, you can attach a MutationObserver to it. When the observer fires, check to see if the element you’re curious about exists as a descendant:

    new MutationObserver((_, observer) => {
      if (popup.querySelector('input')) {
        console.log('Input descendant now exists!');
        // Don't keep the observer active once it's served its purpose:
        observer.disconnect();
      }
    }).observe(popup, { childList: true });
    
    // example of asynchronous ajax call
    setTimeout(() => {
      popup.innerHTML = '<div>popup content<input></div>';
    }, 2000);
    <div id="overlay">
      <div id="popup">
      </div>
    </div>

    But while this is possible, it’s pretty bad practice. If you know when an element is going to be created, it’d be much better to put all the functionality for that inside the ajax success callback, rather than use MutationObserver (which should generally be reserved only for situations when other options are impossible, like when you don’t have control over the code).

    For elements loaded after a network request, you can also use ajaxComplete with jQuery:

    const callback =  () => {
      if (popup.querySelector('input')) {
        console.log('Input descendant now exists!');
        // Don't keep the observer active once it's served its purpose:
        $(document).off('ajaxComplete', callback);
      }
    };
    $(document).on('ajaxComplete', callback);
    
    // example of asynchronous ajax call
    $.get({
      url: 'https://jsonplaceholder.typicode.com/todos/1',
      success() {
        popup.innerHTML = '<div>popup content<input></div>';
      }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div id="overlay">
      <div id="popup">
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search