Patrick Desjardins Blog
Patrick Desjardins picture from a conference

How to have a JQuery function using call back with parameter

Posted on: 2012-12-21

Let say that you want to use a JQuery function and do something when this one end. This is possible with callback that most of JQuery function does have. Unfortunatly, you might want to pass data to the call back function when this one may not let you. How to handle this situation? This is what we will see in this short article concerning JQuery and call back function.

First of all, why would we want to pass information to callback? Couldn't we simply use anonymous function and access data from the outer scope? True, but this may lead to big chunk of code and also cause to repeat code. Let take the following example where an Ajax call is done. We want to hide a division, set the value from the ajax call and then display the division again. But, we may not the division already visible, in this case we just want to set the data and display the division.

$.ajax({ type: 'POST', contentType: 'application/json; charset=utf-8', data: /*...*/, dataType: 'json', url: /*...*/, success: function (result) { 
  var resultJson = $.parseJSON(result); if ($("#myDivisionWhereTheDataBelong").is(":visible")) { 
    $("#myDivisionWhereTheDataBelong").slideUp(150, /*Set data from Ajax call here + Show Division Again*/); 
  } else { 
    /*Set data from Ajax call here + Show Division Again*/ 
  } 
} 
}); 

This illustrate the goal of this article. How can you "set the data from Ajax and show the division" without having twice the same code. The first reflex may be to create a function but let's write first the code repeated in both place to illustrate a functionnal code that is simply just not optimized.

$.ajax({ type: 'POST', contentType: 'application/json; charset=utf-8', data: /*...*/, dataType: 'json', url: /*...*/, success: function (result) { 
  var resultJson = $.parseJSON(result); 
  if ($("#myDivisionWhereTheDataBelong").is(":visible")) { 
    $("#myDivisionWhereTheDataBelong").slideUp(150, function(){ 
      $('#FormInput1').val(resultJson.Val1); 
      $('#FormInput2').val(resultJson.Val2); 
      $("myDivisionWhereTheDataBelong").slideDown(150); 
    }); } 
    else { 
      $('#FormInput1').val(resultJson.Val1); 
      $('#FormInput2').val(resultJson.Val2); 
      $("myDivisionWhereTheDataBelong").slideDown(150); 
    } 
  } 
}); 

As you can see, it's not pretty because we duplicate code but it works.

The second step is to create a function but the main problem is that slideUp takes only a call back function that doesn't have any parameter.

var showResult = function(resultJson) { 
  $('#FormInput1').val(resultJson.Val1); 
  $('#FormInput2').val(resultJson.Val2); 
  $("myDivisionWhereTheDataBelong").slideDown(150); 
} 

$.ajax({ type: 'POST', contentType: 'application/json; charset=utf-8', data: /*...*/, dataType: 'json', url: /*...*/, success: function (result) { 
  var resultJson = $.parseJSON(result); 
  if ($("#myDivisionWhereTheDataBelong").is(":visible")) { 
    $("#myDivisionWhereTheDataBelong").slideUp(150,showResult); 
  } else { 
    showResult(resultJson);
   } 
} 
}); 

This won't work because we do not pass to showResult method any parameter, and even by writing showResult(resultJson) it won't do much more. In fact, we need to pass a pointer to a function without parameter.

var showResult = function(resultJson) { 
  return function() { 
    $('#FormInput1').val(resultJson.Val1); 
    $('#FormInput2').val(resultJson.Val2); 
    $("myDivisionWhereTheDataBelong").slideDown(150);
   }; 
  }; 
  
  $.ajax({ type: 'POST', contentType: 'application/json; charset=utf-8', data: /*...*/, dataType: 'json', url: /*...*/, success: function (result) { 
    var resultJson = $.parseJSON(result);
    if ($("#myDivisionWhereTheDataBelong").is(":visible")) { 
      $("#myDivisionWhereTheDataBelong").slideUp(150,showResult(resultJson)); 
    } else { 
      showResult(resultJson)(); 
    } 
  } 
}); 

Here you can see multiple modification. First, the function return an other function. This is because we need a parameterless function for the callback. The first method lets you send additionnal information and return a pointer to a method that have access (because of the closure principle of Javascript) to the parameter of the outer function. The second modifification is in the else. You now call the method which take a single parameter but it requires you to call again the return anonymous function. This is why you have showResult(resultJson)();