0

Part of the html is replaced with the result of an ajax call. During testing, I made that ajax call the exact same thing as what was replaced. The issue was that none of the JQuery UI and "onClick" stuff I had applied to the old html applied to the new one. I tried recalling the functions that applied it again, but it won't work. Strangely enough, it DOES work if I type it directly into the counsel of google chrome (the new-ajax-html gets effected by the JQuery commands).

This is my code, which includes the original setup of the html at the start (which works) and the second set up (which comes after all of the needed elements have been instantiated.):

function set_up() { // <-- if I call this function in the consul, it works.
    $('.delete-button').click(function() {
        var confirm = window.confirm("Are you sure you want to delete? After you save, this file will not be recoverable.")
        if (confirm){
            $(this).parent('.deletable-group').remove()
        }
    });
    $('.field-default[data-multi="True"]').makeMulti(); 
    $("input.field-input-date").datepicker();
    alert("HERE!") //Is reached both times I call the function. So the code above is executing.
}
var options = { 
    target:     '.server-response-box', 
    success:    function() { //<--- Gets called when the ajax call goes through.
        $('.needs-update').each(function( index ) {
            url = "/field/1/" + $('.edit-wrapper').attr('data-entry-ID') + "/" + $(this).attr('data-field-id');
            old_this = this
            $.get(url,function(data){
               $(old_this).replaceWith(data);
            });
        });
        set_up(); // Tries to set everything up again.
    },
    beforeSubmit: function(arr, $form, options) { 
    }
}; 
$('#form').ajaxForm(options);
set_up(); //<-- sets it all up the first time.
sinθ
  • 11,093
  • 25
  • 85
  • 121
  • Use `$(document).on('click', '.delete-button', function() {` instead. This uses `.on()` to bind a click event to all current and future `.delete-button` elements. Unless you want the whole of `set_up()` to run again, in which case use Brad M's solution. – Joe Jun 26 '13 at 16:27
  • It looks like set_up() is being called before the replace happens. – Chris Charles Jun 26 '13 at 16:27

3 Answers3

4

set_up(); // Tries to set everything up again.

This line inside your ajaxForm success callback function should only execute after all your GET requests execute.

var getRequests = [];
$('.needs-update').each(function( index ) {
    url = "/field/1/" + $('.edit-wrapper').data('entry-ID') + "/" +  $(this).data('field-id');
    old_this = this;
    var ajaxGet = $.get(url,function(data){
        $(old_this).replaceWith(data);
    });
    getRequests.push(ajaxGet);
});
$.when.apply($, getRequests).done(set_up); // Tries to set everything up again.

What this does is create an array of deferred objects for all your GET requests, and when they finish, the set_up function is called.

Edit - Changed use of .attr(data-stuff) to just .data(stuff). Note, .data() will cast a value into string/number/bool, but in this case, it's all concatenated to string. Copy and paste the following into the console to see.

$(this).data('id', 1);
var x = "test" + ($(this).data('id') + $(this).data('id'));
var y = "test" + $(this).data('id') + $(this).data('id');
console.log(x); // "test2"
console.log(y); // "test11"
Brad M
  • 7,857
  • 1
  • 23
  • 40
3

For dynamically added content, you'll need to use delegated event listeners. Check out the documentation for jQuery's on() for more details.

Something like:

$(document).on('click', '.delete-button', function() {...});

UPDATE

As others have pointed out, $.get() is asynchronous. You're calling set_up() once all the calls are made, but not necessarily after they have returned. To do this, keep track of how many have returned using a counter and then call set_up() once they are all complete:

var needsUpdate = $('.needs-update');
var numberToUpdate = needsUpdate.length;
var numberUpdated = 0;

needsUpdate.each(function( index ) {
    url = "/field/1/" + $('.edit-wrapper').attr('data-entry-ID') + "/" + $(this).attr('data-field-id');
    old_this = this
    $.get(url,function(data){
        numberUpdated++;
       $(old_this).replaceWith(data); //update HTML

       if(numberUpdated === numberToUpdate) {
            setup(); //when all HTML added, then initialize widgets and add listeners
       }
    });
});
cfs
  • 10,610
  • 3
  • 30
  • 43
  • It is legitimate to attach event handlers to content added through ajax. Delegated listeners are not a requirement. – Brad M Jun 26 '13 at 16:30
  • I had the same answer on a similar question here http://stackoverflow.com/questions/4208219/how-to-do-following-mask-input-problem/10203361#10203361 – Andy Brudtkuhl Jun 26 '13 at 16:31
  • Thanks, but that only solves the click part. What about the datepicker and .makeMulti? – sinθ Jun 26 '13 at 16:36
  • @MikeG delegation works for event, not plugin. In this case, you have to reinitialize plugin on new added content. See BradM's answer which is then more appropriate – A. Wolff Jun 26 '13 at 16:38
  • @MikeG I've updated my answer to address the issues with your plugins – cfs Jun 26 '13 at 16:43
0

If you have an older version of jQuery (like 1.6 and older), try using

$(element).live("event", function(e) {
bla bla bla;
});
Alin Florin
  • 387
  • 1
  • 4
  • 17