JQuery: 'Uncaught TypeError: Illegal invocation' à la demande ajax - plusieurs éléments

112

J'ai deux éléments de sélection, A et B: lorsque l'option sélectionnée par A change, les options de B doivent être mises à jour en conséquence. Chaque élément dans A implique de nombreux éléments dans B, c'est une relation un-à-plusieurs (A contient des nations, B devrait contenir des villes situées dans la nation donnée).

La fonction do_ajaxdoit exécuter la requête asynchrone:

function do_ajax(elem, mydata, filename)
{
    $.ajax({
        url: filename,
        context: elem,
        data: mydata,
        datatype: "html",
        success: function (data, textStatus, xhr) {
            elem.innerHTML = data;
        }
    });
}

Afin de mettre à jour les options de B, j'ai ajouté un appel de fonction dans l' onChangeévénement de A. Voici la fonction qui s'exécute lorsque l'événement onChange (of A) est déclenché:

function my_onchange(e) // "e" is element "A"
{
    var sel_B = ... ; // get select element "B"

    // I skipped some code here
    // ...

    var data = {
        'mode': 'filter_city',
        'id_A': e[e.selectedIndex]
    };
    do_ajax(city_sel, data, 'ajax_handler.php');
}

}

J'ai lu dans des documents JQuery qui datapeuvent être un tableau (paires clé / valeur). J'obtiens l'erreur si je mets:

var data = {
        'mode': 'filter_city',
        'id_A': e[e.selectedIndex]
};

Au lieu de cela, je n'obtiens pas cette erreur si mes données sont une chaîne:

var data = 'mode=filter_city&id_A=' + e[e.selectedIndex];

Mais j'ai besoin de la "version tableau" de la variable, dans mon code php côté serveur.

Le Uncaught TypeError: Illegal invocationse trouve dans le fichier "jquery-1.7.2.min.js", qui est entièrement compressé, donc je n'ai pas pu déterminer quelle partie du code a provoqué l'erreur.

Y a-t-il un paramètre que je peux modifier dans mon code pour qu'il accepte les données sous forme de tableau associatif?

Nadir Sampaoli
la source

Réponses:

151

Grâce à l'entretien avec Sarfraz, nous avons pu trouver la solution.

Le problème était que je passais un élément HTML au lieu de sa valeur, ce qui est en fait ce que je voulais faire (en fait, dans mon code php, j'ai besoin de cette valeur comme clé étrangère pour interroger ma citiestable et filtrer les entrées correctes).

Donc, au lieu de:

var data = {
        'mode': 'filter_city',
        'id_A': e[e.selectedIndex]
};

ça devrait être:

var data = {
        'mode': 'filter_city',
        'id_A': e[e.selectedIndex].value
};

Remarque: vérifiez la réponse de Jason Kulatunga , il cite le document JQuery pour expliquer pourquoi le passage d'un élément HTML causait des problèmes.

Nadir Sampaoli
la source
exactement ce que je faisais. Oublié d'utiliser .val ()
Usman Shaukat
Je passais l'option, d'un élément html select dans une variable. Je n'ai pas remarqué que ce n'était pas du texte brut mais du HTML.
Sterling Diaz
46

À partir de la documentation jQuery pour processData:

processData Boolean
Par défaut: true
Par défaut, les données transmises à l'option data en tant qu'objet (techniquement, autre chose qu'une chaîne) seront traitées et transformées en une chaîne de requête, correspondant au type de contenu par défaut "application / x-www -form-urlencoded ". Si vous souhaitez envoyer un DOMDocument ou d'autres données non traitées, définissez cette option sur false.

Source: http://api.jquery.com/jquery.ajax

Il semble que vous allez devoir utiliser processDatapour envoyer vos données au serveur, ou modifier votre script php pour prendre en charge les paramètres encodés de la chaîne de requête.

Jason Kulatunga
la source
1
C'est vrai. Si j'avais pu le voir avant, cela m'aurait signalé l'erreur réelle dans mon code. Merci, j'ajouterai une note dans ma réponse.
Nadir Sampaoli
25

J'obtenais cette erreur lors de la publication d'un objet FormData car je ne configurais pas correctement l'appel ajax. La configuration ci-dessous a résolu mon problème.

var myformData = new FormData();        
myformData.append('leadid', $("#leadid").val());
myformData.append('date', $(this).val());
myformData.append('time', $(e.target).prev().val());

$.ajax({
    method: 'post',
    processData: false,
    contentType: false,
    cache: false,
    data: myformData,
    enctype: 'multipart/form-data',
    url: 'include/ajax.php',
    success: function (response) {
        $("#subform").html(response).delay(4000).hide(1); 
    }
});
Mike Volmar
la source
Merci mec. u sauvé ma journée et mon problème est résolu en ajoutant "processData: false, contentType: false, cache: false," dans mon corps ajax. Merci beaucoup.
CumaTekin
11

J'ai lu dans la documentation JQuery que les données peuvent être un tableau (paires clé / valeur). J'obtiens l'erreur si je mets:

Ceci est un objet pas un tableau:

var data = {
        'mode': 'filter_city',
        'id_A': e[e.selectedIndex]
};

Vous voulez probablement:

var data = [{
        'mode': 'filter_city',
        'id_A': e[e.selectedIndex]
}];
Sarfraz
la source
1
il ne jette plus cette erreur mais il semble que ces données ne soient pas transmises à mon $_GETtableau côté serveur ( var_export($_GET)sorties array ( 'undefined' => 'undefined', ))
Nadir Sampaoli
@nadirs: Essayez de définir le type de méthode dans votre $.ajaxgestionnaire:type:'get',
Sarfraz
@Sarfraz le résultat est le même. Côté serveur, les dataclés doivent être trouvées dans le tableau GET, non? Ou peut-être qu'ils sont envoyés via une autre méthode de demande de toute façon?
Nadir Sampaoli
@nadirs: Quelque chose comme ça fonctionne data: {foo:'myfoo', bar:'mybar'}, il pourrait y avoir un autre problème, je pense.
Sarfraz
@Sarfraz Je suis un idiot, j'envoyais un objet HTML e[e.selectedIndex]alors que j'aurais dû passer sa valeur e[e.selectedIndex].value. Après avoir corrigé cette faille, la notation objet fonctionne correctement.
Nadir Sampaoli
7

A eu le même problème récemment, résolu en ajoutant traditional: true,

déco
la source
Cela fonctionne réellement, je suppose que pour les navigateurs modernes uniquement
barnacle.m
0
function do_ajax(elem, mydata, filename)
{
    $.ajax({
        url: filename,
        context: elem,
        data: mydata,
        **contentType: false,
        processData: false**
        datatype: "html",
        success: function (data, textStatus, xhr) {
            elem.innerHTML = data;
        }
    });
}
Derly Pacheco
la source
4
Une bonne réponse est plus qu'un simple extrait de code. Il doit expliquer pourquoi cela répond à la question initiale et fournir des liens vers la documentation pertinente, si disponible.
JSTL
Sans les deux champs contentTypeet processData, l'erreur continuera à s'afficher. J'ai ajouté les deux champs et cela a fonctionné pour moi. Je pense qu'op essayait d'indiquer les deux domaines importants.
Ekundayo Blessing Funminiyi
-1
$.ajax({
                    url:"",
                    type: "POST",
                    data: new FormData($('#uploadDatabaseForm')[0]),
                    contentType:false,
                    cache: false,
                    processData:false,
                    success:function (msg) {}
                  });
Nitin Sharma
la source
7
Les réponses sont plus utiles si vous incluez une explication.
Jon B
-2

Essaye ça:

            $.ajax({
                    url:"",
                    type: "POST",
                    data: new FormData($('#uploadDatabaseForm')[0]),
                    contentType:false,
                    cache: false,
                    processData:false,
                    success:function (msg) {}
                  });
Ali Asad
la source