jQuery serialize не реєструє прапорці


76

Я використовую jQuery.serialize для отримання всіх полів даних у формі.

Моя проблема полягає в тому, що він не отримує прапорці, які не встановлені.

Це включає в себе це:

<input type="checkbox" id="event_allDay" name="event_allDay" class="checkbox" checked="checked" />

але не це

<input type="checkbox" id="event_allDay" name="event_allDay" class="checkbox" />

Як я можу отримати "значення" прапорців, які не встановлено?


2
Що ми робимо в ASP Net, це мати прихований вхід: <input type="checkbox" id="event_allDay" name="event_allDay" class="checkbox" checked="checked" Value="On" /> <input type="hidden" name="event_allDay" Value="Off" /> таким чином, якщо він не позначений, він прийме значення прихованого
Carlos Martinez T

Відповіді:


72

jQuery serializeточно імітує, як стандартна форма буде серіалізована браузером перед додаванням до рядка запиту або тіла POST у запиті. Невстановлені прапорці не включаються браузером, що насправді має сенс, оскільки вони мають логічний стан - вони або вибрані користувачем (включені), або не вибрані користувачем (не включені).

Якщо вам потрібно, щоб це було в серіалі, вам слід запитати себе "чому? Чому б просто не перевірити його наявність у даних?".

Майте на увазі, що якщо спосіб серіалізації даних форми JavaScript поводиться інакше, як це робить браузер, тоді ви виключаєте будь-який шанс витонченого погіршення вашої форми. Якщо вам все одно абсолютно потрібно це зробити, просто використовуйте <select>поле з Так / Ні як варіант. Принаймні, тоді користувачі з вимкненим JS не відчужуються від вашого веб-сайту, і ви не будете суперечити визначеному поведінці в специфікації HTML.

<select id="event_allDay" name="event_allDay">
   <option value="0" selected>No</option>
   <option value="1">Yes</option>
</select>

Раніше я бачив це на деяких сайтах і завжди думав про себе: "чому б їм просто не встановити прапорець" ?


20
Це значно полегшило б зберігання інформації в БД. Тому що тоді кількість полів із серіалізації дорівнювала б кількості полів у таблиці. Тепер я повинен визначити, які з них відсутні.
Стівен

19
Існує цілком слушний випадок, коли потрібно не встановити прапорці та не встановити перемикачі. Значення для цих полів можуть уже існувати на сервері, і ви просто хочете оновити. Не маючи цих значень у рядку подання, передбачається, що ви щоразу виконуєте повне перезапис запису.
mydoghasworms

4
@mydog: чому це може бути так? Якщо ви запитаєте мене, це здається поганим вибором дизайну. Ці поля ніколи не були б у рядку запиту, якщо браузер надсилав дані форми, то чому б ви спроектували його як інший для JavaScript? Для початку ви повністю усунете будь-який шанс витонченої деградації.
Andy E,

1
@AndyE Іноді у вас є сервер, який вимагає, щоб усі параметри були явними. Чому це може бути рідкісним випадком?
Гленн

1
HTML повинен вести себе як подання, а не приймати рішення щодо того, які дані надсилаються "Контролеру". За інтерпретацію даних повинен відповідати "Контролер" - річ, що обробляє повідомлення форми.
муглійо

79

Щоб спиратися на геніальну відповідь Азатото, я трохи розширив її для свого сценарію:

    /* Get input values from form */
    values = jQuery("#myform").serializeArray();

    /* Because serializeArray() ignores unset checkboxes and radio buttons: */
    values = values.concat(
            jQuery('#myform input[type=checkbox]:not(:checked)').map(
                    function() {
                        return {"name": this.name, "value": false}
                    }).get()
    );

7
у мене не спрацювало, тому я зробив невеликий твік: return {"name": this.name, "value": 'off'}
xeo

1
я тебе люблю. я намагався знайти рішення своєї проблеми, і це прийшло разом із google. Дякую
Джастін

Дякую! Це саме те, що мені потрібно було!
jared_flack

працює лише тоді, коли ви використовуєте serializeArray()не простоserialize()
Chaudhry Waqas

1
Це працювало для мене краще, ніж прийнята відповідь, але "this. checked" дало мені стан прапорця замість використання "this.value". Я також змінив селектор jquery на ": прапорець", оскільки мені потрібні були всі прапорці.
Пол

27

Ти ні, оскільки серіалізація призначена для використання як рядка запиту, і в цьому контексті, не позначений, означає, що його взагалі немає в рядку запиту.

Якщо ви дійсно хочете отримати значення невстановлених прапорців, використовуйте: (неперевірене з курсу)

var arr_unchecked_values = $('input[type=checkbox]:not(:checked)').map(function(){return this.value}).get();

Відповідь нижче розширюється на це приємно.
паровий привід

17

якщо ви хочете додати несеріалізовані прапорці до вашого рядка запиту, додайте до вашої функції подання jquery наступне:

var moreinfo = '';

$('input[type=checkbox]').each(function() {     
    if (!this.checked) {
        moreinfo += '&'+this.name+'=0';
    }
});

Це виключить будь-який шанс витонченого погіршення вашої форми - подані дані будуть різними для користувачів із вимкненою JS.
Andy E

Потрібно сказати, якщо ви використовуєте функцію .serialize (), це найкраще рішення var data = $ ("# userinput_form"). Serialize (); $ ('# userinput_form input [type = checkbox]: not (: check)'). each (function () {data + = '&' + this.name + '= 0';});
windmaomao

5

jQuery serialize отримує атрибут value вхідних даних.

Тепер як змусити прапорець та перемикач працювати? Якщо ви встановите клік для прапорця або перемикача 0 або 1, ви зможете побачити зміни.

$( "#myform input[type='checkbox']" ).on( "click", function(){
     if ($(this).prop('checked')){
          $(this).attr('value', 1);
     } else {
          $(this).attr('value', 0);
     }
 }); 

 values = $("#myform").serializeArray();

а також коли ви хочете встановити прапорець із перевіреним статусом, наприклад, php

<input type='checkbox' value="<?php echo $product['check']; ?>" checked="<?php echo $product['check']; ?>" />

2
Цей код працює. В основному це робить елемент керування прапором схожим на звичайний вхід (тип textабо a select) до serialize()функції, надаючи прапорцеві valueвластивість - яка синхронізується із перевіреним статусом. І це більш елегантно, ніж обрана відповідь.
Аннабель

для .Net MVC використання значень True і False дозволить магії відображення моделі mvc встановити властивості вашої булевої моделі. І додайте ці атрибути до вашого <input>, щоб отримати правильний візуалізацію подання: value = "@ (Model.Item2.IsCurrent?" True ":" False ")" @ (Model.Item2.IsCurrent? "Check = 'check'" : "")
DavidCC

4

Ось ще одне рішення, яке розширює метод "serializeArray" (зберігаючи вихідну поведінку).

//Store the reference to the original method:

var _serializeArray = $ ji.fn.serializeArray;

//Now extend it with newer "unchecked checkbox" functionality:
$ji.fn.extend({
    serializeArray: function () {
        //Important: Get the results as you normally would...
        var results = _serializeArray.call(this);

        //Now, find all the checkboxes and append their "checked" state to the results.
        this.find('input[type=checkbox]').each(function (id, item) {
            var $item = $ji(item);
            var item_value = $item.is(":checked") ? 1 : 0;
            var item_name = $item.attr('name');
            var result_index = null;
            results.each(function (data, index) {
                if (data.name == item_name) {
                    result_index = index;
                }
            });

            if (result_index != null) {
                // FOUND replace previous value
                results[result_index].value = item_value;
            }
            else {
                // NO value has been found add new one
                results.push({name: item_name, value: item_value});
            }
        });
        return results;
    }
});

Це насправді додасть булеві результати "true" або "false", але якщо ви бажаєте, ви можете використовувати "1" і "0" відповідно, змінивши значення на value: $item.is(":checked") ? 1 : 0.

Використання

Як зазвичай, викликайте метод у формі: $form.serialize()або $form.serializeArray(). Що трапляється, це serializeвикористовує serializeArrayбудь-який спосіб, тож ви отримуєте належні результати (хоча і в іншому форматі), незалежно від того, який метод ви викликаєте.


ПОМИЛКА: Моя помилка, коли прапорець "true", він все одно додасть параметр із звичайним значенням "on". Збираюся це виправити ...
bigp

якщо прапорець встановлений, ви отримаєте в результаті 2 значення з однаковим іменем ... одне з «увімкнено», а те, яке ви додасте в кінці з «1» ...
WonderLand

Я виправив проблему :)
WonderLand

4

Ви можете викликати handleInputs()add у своїй функції подання перед ajax

function handleInputs(){
    $('input[type=checkbox]').each(function() {     
        if (!this.checked) {
            $(this).attr("value","0");
        }else{
            $(this).attr("value","1");
        }
    });
}

Це чудово працює


3

Техніка, яку я використовував у власних системах і яку, на мою думку, застосовує Struts, полягає у включенні ...

<input type="hidden" name="_fieldname" value="fieldvalue"/> 

... безпосередньо біля прапорця як частини моєї логіки створення форми.

Це дозволяє мені відновити, які прапорці були подані у формі, але не вибрані, з невеликою частинкою додаткової логіки, щоб робити різницю, що було подано і що було перевірено, у вас є ті, які не позначено. Подання також однакове за змістом, незалежно від того, використовуєте ви подання у стилі HTML або AJAX.

Залежно від технології, яку ви використовуєте на стороні сервера, тоді ви можете використовувати цей синтаксис ...

<input type="hidden" name="_fieldname[]" value="fieldvalue"/>

... для спрощення захоплення цих значень у вигляді списку.


3

Для ASP.NET MVC ми успішно зберігаємо форму з прапорцями через AJAX POST із наступним, що є комбінацією декількох методів, на які посилається ця публікація, включаючи пропозицію @Jecoms :

var form = $('#myForm');
// Serialize the form into a JavaScript object using the jQuery.serializeObject plugin
// https://plugins.jquery.com/serializeObject/
var data = form.serializeObject();
// Change the submitted value of checkboxes to the value of the checked property
$('#myForm input[type=checkbox]').each( function () { data[this.name] = this.checked; } );
// For a MVC controller, convert the JS object back into a query string using jQuery.param function
data = $.param(data);
// Perform AJAX POST with the form data
$.ajax({
    async: true,
    url: 'mvcActionMethodURL',
    type: 'POST',
    data: data,
    success: function (data, textStatus, xhr) {

    },
    error: function (xhr, status, error) {

    }
});

2

Однією з причин використання нестандартної серіалізації прапорців, яка не розглядається у питанні чи поточних відповідях, є лише десеріалізація (зміна) полів, явно вказаних у серіалізованих даних - наприклад, коли ви використовуєте серіалізацію та десеріалізацію jquery / з файлу cookie для збереження та завантаження преференцій.

Томас Данемар впровадив модифікацію стандартного serialize()методу, щоб додатково взяти checkboxesAsBoolsопцію: http://tdanemar.wordpress.com/2010/08/24/jquery-serialize-method-and-checkboxes/ - це схоже на реалізацію, перелічену вище @mydoghasworms, але також інтегрований у стандартну серіалізацію.

Я скопіював його на Github на випадок, якщо хтось хоче вдосконалити в будь-який момент: https://gist.github.com/1572512

Крім того, плагін "jquery.deserialize" тепер буде правильно десериалізувати значення прапорець, серіалізовані за допомогою checkboxesAsBools, та ігнорувати прапорці, які не згадуються в серіалізованих даних: https://github.com/itsadok/jquery.deserialize


2
var checkboxes = $('#myform').find('input[type="checkbox"]');
$.each( checkboxes, function( key, value ) {
    if (value.checked === false) {
        value.value = 0;
    } else {
        value.value = 1;
    }
    $(value).attr('type', 'hidden');
});
$('#myform').serialize();

3
Не могли б ви пояснити свою відповідь взагалі?
Бен,

Ця відповідь змінює прапорець у приховане поле, тому його можна серіалізувати. Ця відповідь робить форму одноразовим використанням, однак, як модифікується DOM.
Надання

2

Фокус у тому, щоб перехопити повідомлення форми та змінити прапорці на приховані поля введення.

Приклад: Звичайна подача

$('form').on("submit", function (e) {
    //find the checkboxes
    var $checkboxes = $(this).find('input[type=checkbox]');

    //loop through the checkboxes and change to hidden fields
    $checkboxes.each(function() {
        if ($(this)[0].checked) {
            $(this).attr('type', 'hidden');
            $(this).val(1);
        } else {
            $(this).attr('type', 'hidden');
            $(this).val(0);
        }
    });
});

Приклад: AJAX

Вам потрібно проскочити ще кілька обручів, якщо ви публікуєте форму через ajax, щоб не оновлювати інтерфейс.

$('form').on("submit", function (e) {
    e.preventDefault();

    //clone the form, we don't want this to impact the ui
    var $form = $('form').clone();

    //find the checkboxes
    var $checkboxes = $form.find('input[type=checkbox]');

    //loop through the checkboxes and change to hidden fields
    $checkboxes.each(function() {
        if ($(this)[0].checked) {
            $(this).attr('type', 'hidden');
            $(this).val(1);
        } else {
            $(this).attr('type', 'hidden');
            $(this).val(0);
        }
    });

    $.post("/your/path", $form.serialize());

2

Це встановить значення прапорця форми у логічні значення, використовуючи їх перевірений стан.

var form = $('#myForm');
var data = form.serializeObject();

$('#myForm input[type=checkbox]').each(function() { data[this.name] = this.checked; });

Фреймворк, який ми використовуємо, створює два входи з однаковою назвою, що призводить до несподіваної поведінки при серіалізації форми. Я б отримав кожне значення прапорця, проаналізований як двоелементний масив із рядковими значеннями. Залежно від того, як ви зіставляєте дані на стороні сервера, ви можете отримати непередбачені результати.


1
serializeObject () видається плагіном jQuery: plugins.jquery.com/serializeObject
iCode

Там дуже маленький serializeObject(): benalman.com/projects/jquery-misc-plugins/#serializeobject
Bernhard Döbler

1

Використання вибраних полів, як запропонував Енді, не завжди є найкращим варіантом для користувальницької роботи, оскільки для цього потрібні два клацання миші замість одного.

Більше того, "Select" використовує набагато більше місця в інтерфейсі, ніж прапорець.

Відповідь Еша - просте рішення, але не працює у випадку з полями масиву .

У моєму контексті у мене є форма змінної довжини, яка містить рядки, що відображають поєднання тексту та полів:

<input type="checkbox" value="1" name="thisIsAChkArray[]"/> 
<input type="text" value="" name="thisIsATxtArray[]"/>

Для декодування розміщених даних важливий порядок елементів масиву. Просто додавання непроверених елементів до звичайної серіалізації Jquery не зберігає порядок елементів рядків.

Ось запропоноване рішення на основі відповіді Еша:

(function($) {
  $.fn.serializeWithChkBox = function() {
    // perform a serialize form the non-checkbox fields
    var values = $(this).find('select')
                        .add(  $(this).find('input[type!=checkbox]') )
                        .serialize();
    // add values for checked and unchecked checkboxes fields
    $(this).find('input[type=checkbox]').each(function() {
      var chkVal = $(this).is(':checked') ? $(this).val() : "0";
      values += "&" + $(this).attr('name') + "=" + chkVal;
    });
    return values;
  }
})(jQuery);

1

У мене була подібна проблема, і наступне дозволило мені зібрати всі введені значення форми та позначити / зняти прапорці.

var serialized = this.$('#myform input').map(function() {
return { name: this.name, id: this.id, value: this.checked ? "checked" : "false" };
});

"this. $" є специфічним для програми додатків Zendesk, з якою я працював над цим рішенням.
wooz16

1

Цей приклад передбачає, що ви хочете опублікувати форму назад через, serializeа не serializeArray, і що невстановлений прапорець означає false:

var form = $(formSelector);
var postData = form.serialize();

var checkBoxData = form.find('input[type=checkbox]:not(:checked)').map(function () {
    return encodeURIComponent(this.name) + '=' + false;
}).get().join('&');

if (checkBoxData) {
    postData += "&" + checkBoxData;
}

$.post(action, postData);

Мені подобається not(:checked)селектор
Бернхард Дьоблер

1

Для тих, хто використовує serialize()функцію:

(function ($) {
    var serialize = $.fn.serialize;

    $.fn.serialize = function () {
        let values = serialize.call(this);
        let checkboxes = [];

        checkboxes = checkboxes.concat(
            $('input[type=checkbox]:not(:checked)', this).map(
            function () {
                return this.name + '=false';
            }).get()
        );

        if(checkboxes.length > 0)
            values = checkboxes.join('&') + '&' + values;

        return values;
    };
})(jQuery);

0

іноді неперевірене означає інші значення, наприклад, перевірене може означати так, неперевірене ні чи 0,1 тощо, це залежить від значення, яке ви хочете надати .. отже, може бути інший стан крім "непровірений означає, що його взагалі немає в рядку запитів"

"Це значно полегшило б зберігання інформації в БД. Оскільки тоді кількість полів від Serialize дорівнювала б кількості полів у таблиці. Тепер я повинен визначити, які з них відсутні", ви праві, це теж моя проблема. .. отже, я маю перевірити це неіснуюче значення ....

але, можливо, це може бути рішенням? http://tdanemar.wordpress.com/2010/08/24/jquery-serialize-method-and-checkboxes/


1
Якщо неіснування спричиняє проблему, вам слід використовувати <select>параметри так / ні, замість того, щоб створювати щось, що суперечить тому, як специфікація HTML визначає форму для подання.
Andy E

0

просто додайте прихований ввід

<input type="hidden" name="your_specific_name">

не потребує значення, я перевірив, що це працює для мене


1
Будь ласка, вкажіть. Спробуйте додати приклади коду і, можливо, посилання на документацію.
Йотам Омер

0

Ви можете отримати значення вхідних даних за допомогою jquery серіалізувати

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" id="event_allDay" name="event_allDay" checked="checked" onchange="isChecked(this)" value="" />
<script>
    function isChecked(element) {
        $(element).val($(element).is(':checked').toString());
    }
    isChecked('#event_allDay');
</script>


0

Просто, щоб розширити відповіді на відповіді вище, у моєму випадку мені було потрібно надіслати так / ні проти одного серіалізованого ідентифікатора на мій вихідний улов.

Я встановив елементи прапорця, щоб містити ідентифікатор певного стовпця бази даних, він же (за замовчуванням перевірено) :

(Laravel Blade)

<div class="checkbox">
    <label>
        <input type="checkbox" value="{{ $heading->id }}" checked> {{ $heading->name }}
    </label>
</div>

Коли я подав заявку, я захопив дані за допомогою:

(jQuery)

let form = $('#formID input[type="checkbox"]').map(function() {
                return { id: this.value, value: this.checked ? 1 : 0 };
           }).get();

var data = JSON.stringify(form);
$.post( "/your/endpoint", data );

0

Я використав цей спосіб і отримав значення "0" або якщо позначено "1". Це говорить про те, що якщо ім'я введення прапорця не існує в серіалізованому, form_dataто це означає, що воно не встановлено, тоді додайте значення як нуль ( form_data += '&' + name + '=0'), але якщо позначена serialize()функція автоматично додає його.

   /*get all other form inputs*/ 
   var form_data = form.serialize();

    /*get checkboxes*/
    $.each($("#form_id input[type='checkbox']"), function(){
        var name = $(this).attr('name');
        if(form_data.indexOf(name)===-1)form_data += '&' + name + '=0';
    });


-1

Я розміщую рішення, яке працювало для мене!

var form = $('#checkboxList input[type="checkbox"]').map(function() {
               return { name: this.name, value: this.checked ? this.value : "false" };
            }).get();

var data = JSON.stringify(form);

data value is : "[{"name":"cb1","value":"false"},{"name":"cb2","value":"true"},{"name":"cb3","value":"false"},{"name":"cb4","value":"true"}]"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.