У меня есть форма с множеством полей ввода.
Когда я улавливаю событие формы отправки с помощью jQuery, возможно ли получить все поля ввода этой формы в ассоциативный массив?
Ассоциативный? Не обошлось и без некоторой работы, но вы можете использовать универсальные селекторы:
var items = new Array();
$('#form_id:input').each(function (el) {
items[el.name] = el;
});
на самом деле, в ответе Лэнса ассоциативный массив остается неизменным для значений POST и занимает целую строку кода.
почему элементы являются массивом? вы используете его как простой объект. Здесь нет необходимости в массиве
Оли из @ JonathanMoralesVélez (2008) больше не существует для комментариев. 2015 согласен с вами.
$('#myForm').submit(function() {
// get all the inputs into an array.
var $inputs = $('#myForm :input');
// not sure if you wanted this, but I thought I'd add it.
// get an associative array of just the values.
var values = {};
$inputs.each(function() {
values[this.name] = $(this).val();
});
});
Благодаря совету Simon_Weaver вот еще один способ сделать это, используя serializeArray
:
var values = {};
$.each($('#myForm').serializeArray(), function(i, field) {
values[field.name] = field.value;
});
Обратите внимание, что этот фрагмент не будет работать с элементами <select multiple>
.
Похоже, что новые поля формы HTML 5 не работает с serializeArray
в jQuery версии 1.3. Это работает в версии 1.4+.
В более новых версиях jQuery ответ Simon_Weaver более надежен и проще.
@MightyE & @Simon_Weaver - вы правы, это более надежный метод, но он не делает именно то, что искал OP. serializeArray возвращает массив объектов со свойствами name
и value
. Лучшим решением может быть обработка вывода из serializeArray в любой требуемый формат.
Ты прав, никф, формат данных теперь другой, когда я смотрю на него более внимательно. На самом деле, я удивлен, что для этого нет встроенной поддержки.
Я думаю, что serializeArray () делает именно то, что вы хотите, и это намного меньше кода.
@slacy, как во втором примере в моем ответе?
Способ Саймона не работает (с jquery.1.3.2), если тип ввода - «электронная почта». Я предполагаю, что другие новые типы html5 тоже не появляются. Я не тестировал новый jquery
@gnibbler - я только что тестировал это на jQuery 1.4.4 и 1.5.1, и он работает с обеими этими версиями.
@nickf, полезно знать. Я подумал, что они будут включены на каком-то этапе
Что касается первого варианта, как насчет элементов <select>
? Я попробовал var $inputs = $('#new-ticket :input, :select');
, но это не сработало. Кто-нибудь знает, как это сделать, потому что я не думаю, что делаю это правильно.
@Nathan, вам следует использовать $("#new-ticket :input, #new-ticket :select")
или даже лучше $(":input, :select", "#new-ticket")
@nickf, могу я попросить вас взглянуть на вопрос jquery по другой теме здесь: stackoverflow.com/questions/13137404/…?
Ссылка HTML5 - это 403.
почему вы используете $ input? Что это за синтаксис?
@Kyborek: это не синтаксис, это соглашение, элементы dom помечены символом $, не знаю, откуда он взялся, но я делаю ставку на сообщество PHP, в них отсутствовал символ $ в переменных.
убедитесь, что у всех ваших входов есть имена, иначе это не сработает :)
$('#myform').serializeArray()
- это все, что вам нужно, $.each...
просто создает тот же объект JavaScript, который уже был создан serializeArray. (+1 @slacy)
Это решение работает только с тегами «input» html; не будет повторять, например, в текстовом поле или выбирать.
$('#myForm').bind('submit', function () {
var elements = this.elements;
});
Переменная elements будет содержать все входные данные, выборки, текстовые поля и наборы полей в форме.
Поздно к вечеринке по этому вопросу, но это еще проще:
$('#myForm').submit(function() {
// Get all the forms elements and their values in one step
var values = $(this).serialize();
});
Это действительно лучший ответ. Он даже сохраняет любое форматирование массива, которое может быть у вас для полей ввода. Я не думаю, что ответ nickf действительно сохранил бы ваши структуры данных в неприкосновенности, если бы он был сформирован, например, с помощью Zend_Form, где у вас были бы field [something] и field [something_else] в качестве имен входов ... по крайней мере семантически я не понимаю, как бы это было ...
Согласно документации API jQuery, .serialize()
(api.jquery.com/serialize) помещает все элементы формы в одну строку, готовую для добавления к URL-адресу в строке запроса, по сути имитируя запрос формы GET. Это не приведет к тому, что выполняет ответ nickf.
Стоит знать: .serialize()
также работает только с элементами формы. Таким образом, $('form select').serialize()
будет сериализовать данные только для выборок.
Вместо того, чтобы повторять $('#myForm')
, используйте $ (this).
Я использовал это, но моя форма имеет различные скрытые элементы (не скрытые, как в типе, я имею в виду визуально), которые я не хотел бы включать в сериализацию.
Плагин jquery.form может помочь с тем, что ищут другие, которые в конечном итоге ответят на этот вопрос. Я не уверен, делает ли он то, что вы хотите, или нет.
Также есть функция serializeArray.
Когда мне нужно было выполнить вызов ajax со всеми полями формы, у меня были проблемы с селектором :Вход, возвращающим все флажки, независимо от того, отмечены они или нет. Я добавил новый селектор, чтобы просто получить элементы формы, которые можно отправить:
$.extend($.expr[':'],{
submitable: function(a){
if ($(a).is(':checkbox:not(:checked)'))
{
return false;
}
else if ($(a).is(':input'))
{
return true;
}
else
{
return false;
}
}
});
использование:
$('#form_id :submitable');
Я еще не тестировал его с несколькими полями выбора, но он работает для получения всех полей формы так, как это делает стандартная отправка.
Я использовал это при настройке параметров продукта на сайте OpenCart, чтобы включить флажки и текстовые поля, а также стандартный тип поля выбора.
Не забудьте о флажках и переключателях -
var inputs = $("#myForm :input");
var obj = $.map(inputs, function(n, i) {
var o = {};
if (n.type == "radio" || n.type == "checkbox")
o[n.id] = $(n).attr("checked");
else
o[n.id] = $(n).val();
return o;
});
return obj
У меня была такая же проблема, но я решил ее по-другому.
var arr = new Array();
$(':input').each(function() {
arr.push($(this).val());
});
arr;
Он возвращает значение всех полей ввода. Вы можете изменить $(':input')
, чтобы быть более конкретным.
То же решение, что и Nickf, но с учетом имен входных массивов например
<input type = "text" name = "array[]" />
values = {};
$("#something :input").each(function() {
if (this.name.search(/\[\]/) > 0) //search for [] in name
{
if (typeof values[this.name] != "undefined") {
values[this.name] = values[this.name].concat([$(this).val()])
} else {
values[this.name] = [$(this).val()];
}
} else {
values[this.name] = $(this).val();
}
});
Была аналогичная проблема с небольшим поворотом, и я подумал, что выкину это. У меня есть функция обратного вызова, которая получает форму, поэтому у меня уже был объект формы, и я не мог простых вариантов на $('form:input')
. Вместо этого я придумал:
var dataValues = {};
form.find('input').each(
function(unusedIndex, child) {
dataValues[child.name] = child.value;
});
Это похожая, но не идентичная ситуация, но я нашел эту ветку очень полезной и подумал, что добавлю ее в конец и надеюсь, что кто-то еще сочтет ее полезной.
serializeArray
jQuery не включает отключенные поля, поэтому, если они вам тоже нужны, попробуйте:
var data = {};
$('form.my-form').find('input, textarea, select').each(function(i, field) {
data[field.name] = field.value;
});
serialize () - лучший метод. @ Christopher Parker говорит, что anwser Никфа выполняет больше, однако он не принимает во внимание, что форма может содержать текстовое поле и выбирать меню. Гораздо лучше использовать serialize (), а затем манипулировать им по мере необходимости. Данные из serialize () можно использовать либо в сообщениях Ajax, либо в get, поэтому здесь нет никаких проблем.
Иногда я считаю, что получать по одному более полезно. Для этого есть следующее:
var input_name = "firstname";
var input = $("#form_id :input[name='"+input_name+"']");
Добавление [0].value
к этому, то есть $(...)[0].value;
дало мне значение ввода напрямую, спасибо!
Если вам нужно получить несколько значений из входов, и вы используете [] для определения входов с несколькими значениями, вы можете использовать следующее:
$('#contentform').find('input, textarea, select').each(function(x, field) {
if (field.name) {
if (field.name.indexOf('[]')>0) {
if (!$.isArray(data[field.name])) {
data[field.name]=new Array();
}
data[field.name].push(field.value);
} else {
data[field.name]=field.value;
}
}
});
Надеюсь, это кому-то поможет. :)
// This html:
// <form id = "someCoolForm">
// <input type = "text" class = "form-control" name = "username" value = "...." />
//
// <input type = "text" class = "form-control" name = "profile.first_name" value = "...." />
// <input type = "text" class = "form-control" name = "profile.last_name" value = "...." />
//
// <input type = "text" class = "form-control" name = "emails[]" value = "..." />
// <input type = "text" class = "form-control" name = "emails[]" value = ".." />
// <input type = "text" class = "form-control" name = "emails[]" value = "." />
// </form>
//
// With this js:
//
// var form1 = parseForm($('#someCoolForm'));
// console.info(form1);
//
// Will output something like:
// {
// username: "test2"
// emails:
// 0: "[email protected]"
// 1: "[email protected]"
// profile: Object
// first_name: "..."
// last_name: "..."
// }
//
// So, function below:
var parseForm = function (form) {
var formdata = form.serializeArray();
var data = {};
_.each(formdata, function (element) {
var value = _.values(element);
// Parsing field arrays.
if (value[0].indexOf('[]') > 0) {
var key = value[0].replace('[]', '');
if (!data[key])
data[key] = [];
data[value[0].replace('[]', '')].push(value[1]);
} else
// Parsing nested objects.
if (value[0].indexOf('.') > 0) {
var parent = value[0].substring(0, value[0].indexOf("."));
var child = value[0].substring(value[0].lastIndexOf(".") + 1);
if (!data[parent])
data[parent] = {};
data[parent][child] = value[1];
} else {
data[value[0]] = value[1];
}
});
return data;
};
http://api.jquery.com/serializearray/
$('#form').on('submit', function() {
var data = $(this).serializeArray();
});
Это также можно сделать без jQuery, используя объект XMLHttpRequest Level 2 FormData.
http://www.w3.org/TR/2010/WD-XMLHttpRequest2-20100907/#the-formdata-interface
var data = new FormData([form])
Вот еще одно решение, таким образом вы можете получить все данные о форме и использовать их в вызове на стороне сервера или в чем-то еще.
$('.form').on('submit', function( e )){
var form = $( this ), // this will resolve to the form submitted
action = form.attr( 'action' ),
type = form.attr( 'method' ),
data = {};
// Make sure you use the 'name' field on the inputs you want to grab.
form.find( '[name]' ).each( function( i , v ){
var input = $( this ), // resolves to current input element.
name = input.attr( 'name' ),
value = input.val();
data[name] = value;
});
// Code which makes use of 'data'.
e.preventDefault();
}
Затем вы можете использовать это с вызовами ajax:
function sendRequest(action, type, data) {
$.ajax({
url: action,
type: type,
data: data
})
.done(function( returnedHtml ) {
$( "#responseDiv" ).append( returnedHtml );
})
.fail(function() {
$( "#responseDiv" ).append( "This failed" );
});
}
Надеюсь, это будет полезно для любого из вас :)
Все ответы хороши, но если есть поле, которое вы хотели бы игнорировать в этой функции? Просто дайте полю свойство, например ignore_this:
<input type = "text" name = "some_name" ignore_this>
И в вашей функции сериализации:
if (!$(name).prop('ignorar')){
do_your_thing;
}
Таким образом вы игнорируете некоторые поля.
Это больше комментарий, чем ответ, поскольку он не отвечает на исходный вопрос.
Может потому, что у него уже есть масса ответов? Это дополнение к полученным им ответам.
Я бы реализовал это с именем класса, например обязательным, если ввод должен быть заполнен. Тогда я могу проверить $('.mandatory');
и !$('.mandatory');
Измените ignore_this
на data-ignore-this = "true"
вместо создания собственных атрибутов, которые не проверяют w3c
Я использую этот код без каждого цикла:
$('.subscribe-form').submit(function(e){
var arr=$(this).serializeArray();
var values = {};
for(i in arr){values[arr[i]['name']]=arr[i]['value']}
console.info(values);
return false;
});
Кажется странным, что никто не проголосовал за и не предложил краткого решения для получения данных списка. Вряд ли какие-либо формы будут одномерными объектами.
Обратной стороной этого решения, конечно же, является то, что к вашим одноэлементным объектам нужно будет обращаться по индексу [0]. Но, IMO, это намного лучше, чем использование одного из дюжин-линейных картографических решений.
var formData = $('#formId').serializeArray().reduce(function (obj, item) {
if (obj[item.name] == null) {
obj[item.name] = [];
}
obj[item.name].push(item.value);
return obj;
}, {});
Этот фрагмент кода будет работать вместо имени, электронная почта введите имя полей формы
$(document).ready(function(){
$("#form_id").submit(function(event){
event.preventDefault();
var name = $("input[name='name']",this).val();
var email = $("input[name='email']",this).val();
});
});
Это мое любимое решение, вдохновленное ответами Лэнс Рашинг и Simon_Weaver.
$('#myForm').submit( function( event ) {
var values = $(this).serializeArray();
// In my case, I need to fetch these data before custom actions
event.preventDefault();
});
Результатом является массив объектов, например.
[{name: "start-time", value: "11:01"}, {name: "end-time", value: "11:11"}]
Используя приведенный ниже код,
var inputs = {};
$.each(values, function(k, v){
inputs[v.name]= v.value;
});
его окончательный результат будет
{"start-time":"11:01", "end-time":"11:01"}
Я надеюсь, что это будет полезным, а также самым простым.
$("#form").submit(function (e) {
e.preventDefault();
input_values = $(this).serializeArray();
});
Как ни странно, это не сработало в последней версии jquery 3.4.1.
Попробуйте следующий код:
jQuery("#form").serializeArray().filter(obje =>
obje.value!='').map(aobj=>aobj.name+" = "+aobj.value).join("&")
Пожалуйста, объясните свой ответ
Для нескольких элементов выбора (<select multiple = "multiple">
) я изменил решение от @Jason Norwood-Young, чтобы оно работало.
Ответ (как опубликовано) принимает только значение из первого выбранного элемента, а не все они. Он также не инициализировал и не возвращал data
, первый из которых вызывал ошибку JavaScript.
Вот новая версия:
function _get_values(form) {
let data = {};
$(form).find('input, textarea, select').each(function(x, field) {
if (field.name) {
if (field.name.indexOf('[]') > 0) {
if (!$.isArray(data[field.name])) {
data[field.name] = new Array();
}
for (let i = 0; i < field.selectedOptions.length; i++) {
data[field.name].push(field.selectedOptions[i].value);
}
} else {
data[field.name] = field.value;
}
}
});
return data
}
Использование:
_get_values($('#form'))
Примечание. Вам просто нужно убедиться, что выбранный вами name
имеет добавленный в конец []
, например:
<select name = "favorite_colors[]" multiple = "multiple">
<option value = "red">Red</option>
<option value = "green">Green</option>
<option value = "blue">Blue</option>
</select>
$("#form-id").submit(function (e) {
e.preventDefault();
inputs = {};
input_serialized = $(this).serializeArray();
input_serialized.forEach(field => {
inputs[field.name] = field.value;
})
console.info(inputs)
});
Хороший вопрос; на самом деле, мне кажется очень странным, что jQuery не имеет функции, которая делает именно это. Существуют функции для получения данных формы в двух разных форматах, но не самый удобный, знаете ли, для сценарии… (Может быть .val () должен возвращать такой массив, если вызывается в элементе формы?)