Как использовать jQuery form.serialize, но исключить пустые поля

107

У меня есть форма поиска с несколькими текстовыми полями и раскрывающимися списками, которые отправляются через GET. Я хотел бы иметь более чистый URL-адрес поиска, удалив пустые поля из строки запроса при выполнении поиска.

var form = $("form");  
var serializedFormStr = form.serialize();  
// I'd like to remove inputs where value is '' or '.' here
window.location.href = '/search?' + serializedFormStr

Есть идеи, как я могу это сделать с помощью jQuery?

Том Винер
источник

Ответы:

167

Я просматривал документы jQuery и думаю, что мы можем сделать это в одной строке, используя селекторы :

$("#myForm :input[value!='']").serialize() // does the job!

Очевидно #myForm получает элемент с идентификатором «Myform» , но то , что было менее очевидным для меня в первый том , что символ пробела необходимо между #myForm и: вход , как это потомок оператора.

: input соответствует всем элементам input, textarea, select и button.

[value! = ''] - атрибут не равен фильтру. Странная (и полезная) вещь заключается в том, что все: типы входных элементов имеют атрибуты значений, даже для выбора, флажков и т. Д.

Наконец, чтобы также удалить входы, где значение было '.' (как указано в вопросе):

$("#myForm :input[value!=''][value!='.']").serialize()

В этом случае сопоставление, то есть размещение двух селекторов атрибутов рядом друг с другом , подразумевает AND. Использование запятой подразумевает ИЛИ. Извините, если это очевидно для специалистов по CSS!

Том Винер
источник
3
@Mvision, это потому, что в этом ответе есть небольшое, но существенное упущение. Для обычных / чистых селекторов CSS в jQuery 1.8 и ранее [value]соответствует любому элементу с value присутствующим атрибутом , включая элементы с пустыми значениями (или без значений). Это связано с ошибкой в ​​более ранних версиях jQuery, которая создавала несоответствие между некоторыми вариантами input[value]и :input[value]. Возьмем, например <input value="foo"><input value=""><input value><input>,; ошибка проиллюстрирована на этой скрипке .
Noyo
4
У меня это сработало: $form.find(":input[value]")- пустые поля не выбирались. Не сработало: $form.find(":input[value!='']")- выбраны все поля. Надеюсь, это кому-то поможет. (jQuery 2.0.0)
Райан Уил
1
$form.find(":input[value]")также работал у меня (jQuery 1.11.0)
GSTAR
Работал только в том случае, если valueатрибут уже был там. Иначе он этого не узнал.
Starcorn
1
В некоторых случаях, когда valueэто установлено программно, это не сработает ( valueне будет существовать как атрибут HTML, но будет как атрибут данных на входе). В тех случаях, попробуйте следующее: $('#myForm :input').filter(function(i) { return ($(this).val().length != 0); }).serialize(). РЕДАКТИРОВАТЬ: только что видел ответ Рича на тот же эффект.
Fateh Khalsa
54

Мне не удалось заставить решение Тома работать (?), Но я смог сделать это, используя .filter()короткую функцию для определения пустых полей. Я использую jQuery 2.1.1.

var formData = $("#formid :input")
    .filter(function(index, element) {
        return $(element).val() != '';
    })
    .serialize();
Богатый
источник
2
Не удалось получить утвержденный ответ, но это отлично сработало! Спасибо!
bfritz
Отвечая на свой вопрос: « :inputСелектор в основном выбирает все элементы управления формы. Выбирает все элементы ввода, текстовой области, выбора и кнопки». источник
Dinei
Да, у Тома сломан . Твой чище, чем моя попытка на этой скрипке. Up'd
Hashbrown
11

Это работает для меня:

data = $( "#my_form input").filter(function () {
        return !!this.value;
    }).serialize();
Р.М.азитов
источник
Что ж, обратный вызов позволяет передавать значения, возвращающие истину, !!повторно набирает все на bool, вы можете попробовать в консоли. !!('test'), !!(5),!!(0)
Aiphee
2
И вместо inputселектора нужно :inputвключать
выборки
Я предлагаю это изменение:data = $( "#my_form :input").filter(function () { return $(this).val() != ""; }).serialize();
Mahoor13
9

Вы можете сделать это с помощью регулярного выражения ...

var orig = $('#myForm').serialize();
var withoutEmpties = orig.replace(/[^&]+=\.?(?:&|$)/g, '')

Тестовые случаи:

orig = "a=&b=.&c=&d=.&e=";
new => ""

orig = "a=&b=bbb&c=.&d=ddd&e=";
new => "b=bbb&d=ddd&"  // dunno if that trailing & is a problem or not
Nickf
источник
.replace (/[^&pting+=\.?(& | $) / g, '') охватывает оба случая. Но я бы добавил .replace (/ & $ /, ''), чтобы удалить завершающий &
Том Винер
15
Нет проблемы, что регулярное выражение не может сделать хуже.
Майкл Кук
3

Я использовал вышеуказанное решение, но для меня это не сработало. Итак, я использовал следующий код

$('#searchform').submit(function(){

            var serializedData = $(this).serializeArray();
            var query_str = '';

            $.each(serializedData, function(i,data){
                if($.trim(data['value'])){
                    query_str += (query_str == '') ? '?' + data['name'] + '=' + data['value'] : '&' + data['name'] + '=' + data['value'];
                }
            });
            console.log(query_str);
            return false;
        });

Может быть кому-то полезно

Раджан Равал
источник
1

Я бы посмотрел исходный код jQuery. В последней версии строка 3287.

Я мог бы добавить функции "serialize2" и "serializeArray2". конечно назовите их чем-нибудь подлым.

Или лучше было бы написать что-нибудь, чтобы вытащить неиспользуемые вары из serializedFormStr. Некоторое регулярное выражение, которое ищет = & в середине строки или заканчивается на = Любые мастера регулярных выражений?

ОБНОВЛЕНИЕ: мне больше нравится ответ rogeriopvl (+1) ... тем более, что я не могу найти никаких хороших инструментов регулярного выражения прямо сейчас.

BuddyJoe
источник
1

Альтернатива решению Рича :

$('#form').submit(function (e) {
  e.preventDefault();

  var query = $(this).serializeArray().filter(function (i) {
    return i.value;
  });

   window.location.href = $(this).attr('action') + (query ? '?' + $.param(query) : '');
});

Пояснения:

  • .submit()подключается к submitсобытию формы
  • e.preventDefault() предотвращает отправку формы
  • .serializeArray() дает нам представление в виде массива строки запроса, которая должна была быть отправлена.
  • .filter() удаляет ложные (включая пустые) значения в этом массиве.
  • $.param(query) создает сериализованное и совместимое с URL-адресом представление нашего обновленного массива
  • установка значения для window.location.hrefотправки запроса
Катандракс
источник
0

В coffeescript сделайте следующее:

serialized_form = $(_.filter($(context).find("form.params input"), (x) -> $(x).val() != '')).serialize()
Джон Гудсен
источник
-1

Возможно, вы захотите взглянуть на функцию jquery .each (), которая позволяет вам перебирать каждый элемент селектора, поэтому таким образом вы можете проверить каждое поле ввода и посмотреть, пусто оно или нет, а затем удалить его из формы используя element.remove (). После этого вы можете сериализовать форму.

Rogeriopvl
источник
1
Единственная проблема с этим состоит в том, что пользователь увидит, что пустые элементы управления исчезают непосредственно перед отправкой страницы. Было бы лучше установить имя "", чтобы сериализация игнорировала его.
Tom Viner