views:

39

answers:

3

I'm using this code:

$newFilter = getNewFilter();

$fieldDropdown = getFieldDropdown(fieldData.field);
$newFilter.append($fieldDropdown);

$typeDropdown = getTypeDropdown($fieldDropdown.data('zenfilter').fieldId, $fieldDropdown.val(), fieldData.type);
$newFilter.append($typeDropdown);

$inputBox = getInputBox($typeDropdown.data('zenfilter').fieldId, $typeDropdown.data('zenfilter').fieldType, $typeDropdown.val(), fieldData.value);
$newFilter.append($inputBox);

And I get a error ($fieldDropdown.data("zenfilter") is null) on the fourth line ($typeDropdown = getTypeDropdown...). This is because the getFieldDropdown didn't finished execution yet. How can I call the functions lineally? Thanks a lot.

Edit: Added the getFieldDropdown function:

getFieldDropdown = function (populateData) {
    var $hiddenInput, i, $obj;

    $hiddenInput = $('<input>', {
        name: defaults.paramName + '[' + nFilters + '][field]',
        type: 'hidden'
    });
    $obj = $('<select></select>', {
        'class': classesHash.individualField,
        name: defaults.paramName + '[' + nFilters + '][fakefield]'
    }).
    data('zenfilter', { fieldId: nFilters }).
    addOption(fieldOptions).
    sortOptions(true).
    selectOptions('').
    change(function(){
        $(this).nextAll('select, div.' + classesHash.individualInputContainer).detach();
        $(this).removeClass(classesHash.incompleteField).after(getTypeDropdown($(this).data('zenfilter').fieldId, $(this).val()));
        $(this).prev('input[type=hidden]').val(defaults.data[$(this).val()].fieldname);
    });
    if (populateData) {
        for (i = 0; i < defaults.data.length; i += 1) {
            if (defaults.data[i].fieldname === populateData) {
                $obj.selectOptions(String(i));
            }
        }
    }

    return $hiddenInput.add($obj);
};

(addOptions, sortOptions and selectOptions are just a plugin's methods to manipulate selects easier, they don't do any AJAX)

A: 

Those functions are called synchronously. What's most likely happening is that getFieldDropdown(fieldData.field) is returning null, or the object that it returns doesn't have the zenfilter property defined internally.

CD Sanchez
You were right, Daniel, ($fieldDropdown.data('zenfilter').fieldId was null. Thanks a lot.
Alejandro García Iglesias
+1  A: 

I assume that getFieldDropdown is an asynchronous call, from your question (a definition for that function would make this question easier to answer).

JavaScript does execute in a single-threaded way; your problem is not that getFieldDropdown doesn't complete, your problem is that it initiates an asynchronous call and then returns. If you want to do work with the results of an asynchronous call, you have to provide that call a callback: a function to execute when it's done.

Assuming the callback is the second, currently un-provided argument to getFieldDropdown, you'd do something like this:

$fieldDropdown = getFieldDropdown(fieldData.field, function(){
    $newFilter.append($fieldDropdown);

    $typeDropdown = getTypeDropdown($fieldDropdown.data('zenfilter').fieldId,$fieldDropdown.val(), fieldData.type);
    $newFilter.append($typeDropdown);

    $inputBox = getInputBox($typeDropdown.data('zenfilter').fieldId,$typeDropdown.data('zenfilter').fieldType, $typeDropdown.val(), fieldData.value);
    $newFilter.append($inputBox);
});

that lets you defer the execution of the stuff that relies on the results of the asynchronous call until those results are there.

DDaviesBrackett
A: 

You will need to edit getFieldDropdown in order to achieve this. Instead of making it execute serially, it is better to re-design so that it can accept a callback method to run when execution is finished. This is the standard way with jQuery:

fieldDropdown = getFieldDropdown(fieldData.field, function () {

  $newFilter.append($fieldDropdown);

  $typeDropdown = getTypeDropdown($fieldDropdown.data('zenfilter').fieldId,   $fieldDropdown.val(), fieldData.type);
  $newFilter.append($typeDropdown);

  $inputBox = getInputBox($typeDropdown.data('zenfilter').fieldId,   $typeDropdown.data('zenfilter').fieldType, $typeDropdown.val(), fieldData.value);
  $newFilter.append($inputBox);

}
);
kgiannakakis