JQuery: 'Uncaught TypeError: Illegal invocation' по запросу ajax - несколько элементов

112

У меня есть два элемента select, A и B: когда выбранный параметр A изменяется, параметры B должны быть соответственно обновлены. Каждый элемент в A подразумевает множество элементов в B, это отношение «один ко многим» (A содержит страны, B должен содержать города, расположенные в данной стране).

Функция do_ajaxдолжна выполнить асинхронный запрос:

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

Чтобы обновить параметры B, я добавил вызов функции в onChangeсобытии A. Вот функция, которая запускается при срабатывании события onChange (of A):

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');
}

}

Я читал в документации JQuery, которая dataможет быть массивом (пары ключ-значение). Я получаю сообщение об ошибке, если ставлю:

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

Вместо этого я не получаю эту ошибку, если мои данные представляют собой строку:

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

Но мне нужна "версия массива" переменной в моем PHP-коде на стороне сервера.

Он Uncaught TypeError: Illegal invocationнаходится в файле «jquery-1.7.2.min.js», который полностью сжат, поэтому я не мог понять, какая часть кода вызвала ошибку.

Есть ли какой-нибудь параметр, который я могу изменить в своем коде, чтобы он принимал данные как ассоциативный массив?

Надир Сампаоли
источник

Ответы:

152

Благодаря разговору с Сарфразом мы смогли найти решение.

Проблема заключалась в том, что я передавал HTML-элемент вместо его значения, что на самом деле я и хотел сделать (на самом деле в моем php-коде мне нужно это значение как внешний ключ для запроса моей citiesтаблицы и фильтрации правильных записей).

Итак, вместо:

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

так должно быть:

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

Примечание: проверьте ответ Джейсона Кулатунги , он цитирует документ JQuery, чтобы объяснить, почему передача элемента HTML вызывала проблемы.

Надир Сампаоли
источник
именно то, что я делал. Забыл использовать .val ()
Усман Шаукат
Я передавал вариант выбора элемента html в переменной. Не заметил, что это был не простой текст, а html.
Стерлинг Диас
46

Из документации jQuery для processData:

processData Boolean
По умолчанию: true
По умолчанию данные, переданные в параметр данных в виде объекта (технически все, кроме строки), будут обработаны и преобразованы в строку запроса, соответствующую типу содержимого по умолчанию application / x-www -form-urlencoded ". Если вы хотите отправить DOMDocument или другие необработанные данные, установите для этого параметра значение false.

Источник: http://api.jquery.com/jquery.ajax

Похоже, вам придется использовать processDataдля отправки данных на сервер или изменить свой php-скрипт для поддержки параметров, закодированных в строке запроса.

Джейсон Кулатунга
источник
1
Это верно. Если бы я мог увидеть это раньше, он указал бы мне на настоящую ошибку в моем коде. Спасибо, в ответ добавлю пометку.
Надир Сампаоли
25

Я получал эту ошибку при публикации объекта FormData, потому что я неправильно настраивал вызов ajax. Установка ниже устранила мою проблему.

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); 
    }
});
Майк Волмар
источник
Спасибо чувак. Ты спас мне день, и моя проблема решена добавлением "processData: false, contentType: false, cache: false" в мое тело ajax. Большое спасибо.
CumaTekin
11

Я читал в документах JQuery, что данные могут быть массивом (пары ключ-значение). Я получаю сообщение об ошибке, если ставлю:

Это объект, а не массив:

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

Вы наверняка захотите:

var data = [{
        'mode': 'filter_city',
        'id_A': e[e.selectedIndex]
}];
Sarfraz
источник
1
он больше не вызывает эту ошибку, но кажется, что эти данные не передаются на $_GETсерверную часть моего массива ( var_export($_GET)выходы array ( 'undefined' => 'undefined', ))
Надир Сампаоли
@nadirs: Попробуйте определить тип метода в своем $.ajaxобработчике:type:'get',
Sarfraz
@Sarfraz результат такой же. На стороне сервера dataключи должны быть в массиве GET, верно? Или, может быть, они все равно отправляются другим методом запроса?
Надир Сампаоли
@nadirs: Что-то вроде этого работает data: {foo:'myfoo', bar:'mybar'}, думаю, может быть другая проблема.
Sarfraz
@Sarfraz Я идиот, я отправлял объект HTML, e[e.selectedIndex]а должен был передать его значение e[e.selectedIndex].value. После исправления этого недостатка объектная нотация работает нормально.
Надир Сампаоли
7

Недавно была такая же проблема, решена добавлением traditional: true,

деко
источник
Это действительно работает, я предполагаю, что только для современных браузеров
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;
        }
    });
}
Дерли Пачеко
источник
4
Хороший ответ больше , чем просто фрагмент кода. Он должен объяснить, почему это отвечает на первоначальный вопрос, и предоставить ссылки на соответствующую документацию, если таковая имеется.
JSTL
Без двух полей contentTypeи processDataошибка будет отображаться. Я добавил два поля, и у меня это сработало. Я думаю, что op пытался указать на два важных поля.
Ekundayo Blessing Funminiyi,
-1
$.ajax({
                    url:"",
                    type: "POST",
                    data: new FormData($('#uploadDatabaseForm')[0]),
                    contentType:false,
                    cache: false,
                    processData:false,
                    success:function (msg) {}
                  });
Нитин Шарма
источник
7
Ответы будут более полезными, если вы включите объяснение.
Jon B
-2

Попробуй это:

            $.ajax({
                    url:"",
                    type: "POST",
                    data: new FormData($('#uploadDatabaseForm')[0]),
                    contentType:false,
                    cache: false,
                    processData:false,
                    success:function (msg) {}
                  });
Али Асад
источник