jQuery serialize không đăng ký hộp kiểm


76

Tôi đang sử dụng jQuery.serialize để truy xuất tất cả các trường dữ liệu trong một biểu mẫu.

Vấn đề của tôi là nó không truy xuất các hộp kiểm không được chọn.

Nó bao gồm điều này:

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

nhưng không phải cái này

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

Làm cách nào để lấy "giá trị" của các hộp kiểm không được chọn?


2
Những gì chúng ta làm trong ASP Net là phải có một đầu vào ẩn: <input type="checkbox" id="event_allDay" name="event_allDay" class="checkbox" checked="checked" Value="On" /> <input type="hidden" name="event_allDay" Value="Off" /> Bằng cách này nó nếu nó không được chọn, nó sẽ mất giá trị của ẩn
Carlos Martinez T

Câu trả lời:


72

jQuery serializebắt chước một cách chặt chẽ cách một biểu mẫu chuẩn sẽ được trình duyệt tuần tự hóa trước khi được nối vào chuỗi truy vấn hoặc nội dung POST trong yêu cầu. Các hộp kiểm bỏ chọn không được trình duyệt bao gồm, điều này thực sự có ý nghĩa vì chúng có trạng thái boolean - chúng được người dùng chọn (được bao gồm) hoặc không được người dùng chọn (không được bao gồm).

Nếu bạn cần nó ở dạng tuần tự, bạn nên tự hỏi mình "tại sao? Tại sao không kiểm tra sự tồn tại của nó trong dữ liệu?".

Hãy nhớ rằng nếu cách JavaScript tuần tự hóa dữ liệu biểu mẫu hoạt động khác với cách trình duyệt thực hiện thì bạn đang loại bỏ bất kỳ cơ hội xuống cấp nào cho biểu mẫu của mình. Nếu bạn vẫn thực sự cần làm điều đó, chỉ cần sử dụng <select>hộp có Có / Không làm tùy chọn. Ít nhất thì sau đó, người dùng bị vô hiệu hóa JS không bị xa lánh khỏi trang web của bạn và bạn sẽ không đi ngược lại hành vi đã xác định trong đặc tả HTML.

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

Tôi đã thấy điều này được sử dụng trên một số trang web trong quá khứ và luôn tự nghĩ, "tại sao họ không chỉ sử dụng một hộp kiểm" ?


20
Nó sẽ làm cho việc lưu trữ thông tin trong DB dễ dàng hơn rất nhiều. Vì khi đó số lượng trường từ Serialize sẽ bằng số trường trong bảng. Bây giờ tôi phải ước lượng cái nào còn thiếu.
Steven

19
Có một trường hợp hoàn toàn tốt cho việc muốn bỏ chọn các hộp kiểm và bỏ đặt các nút radio. Các giá trị cho các trường này có thể đã tồn tại trên máy chủ và bạn chỉ muốn cập nhật. Bằng cách không có những giá trị này trong chuỗi gửi của bạn, nó giả định rằng bạn đang thực hiện ghi đè hoàn toàn bản ghi mỗi lần.
mydoghasworms

4
@mydog: tại sao lại như vậy? Nó có vẻ như là một lựa chọn thiết kế kém nếu bạn hỏi tôi. Những trường đó sẽ không bao giờ có trong chuỗi truy vấn nếu trình duyệt đang gửi dữ liệu biểu mẫu, vậy tại sao bạn lại thiết kế nó khác với JavaScript? Bạn sẽ loại bỏ hoàn toàn mọi cơ hội xuống cấp duyên dáng, bắt đầu.
Andy E

1
@AndyE Đôi khi bạn có một máy chủ yêu cầu tất cả các tùy chọn phải rõ ràng. Tại sao đây sẽ là một trường hợp hiếm?
Glenn

1
HTML phải hoạt động như một dạng xem và không đưa ra quyết định về dữ liệu nào được gửi đến "Bộ điều khiển". Dữ liệu được diễn giải như thế nào nên thuộc trách nhiệm của "Controller" - người xử lý bài đăng của biểu mẫu.
muglio

79

Để xây dựng câu trả lời thiên tài của azatoth, tôi đã mở rộng một chút cho kịch bản của mình:

    /* 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
không phù hợp với tôi nên tôi đã thực hiện một chỉnh sửa nhỏ: return {"name": this.name, "value": 'off'}
xeo

1
Tôi mến bạn. Tôi đã đấu tranh để tìm ra giải pháp cho vấn đề của mình và điều này đã đến cùng với google. Cảm ơn bạn
Justin

Cảm ơn bạn! Đây chính xác là những gì tôi cần!
jared_flack

chỉ hoạt động khi bạn sử dụng serializeArray()không chỉserialize()
Chaudhry Waqas

1
Điều này hoạt động tốt hơn cho tôi so với câu trả lời được chấp nhận, nhưng 'this.checked' đã cho tôi trạng thái hộp kiểm thay vì sử dụng 'this.value'. Tôi cũng đã sửa đổi bộ chọn jquery thành ": hộp kiểm" vì tôi cần tất cả các hộp kiểm.
Paul

27

Bạn không, vì serialize có nghĩa là được sử dụng như một chuỗi truy vấn và trong ngữ cảnh đó, việc bỏ chọn có nghĩa là nó hoàn toàn không có trong chuỗi truy vấn.

Nếu bạn thực sự muốn nhận giá trị của các hộp kiểm không được chọn, hãy sử dụng: (không được kiểm tra ngoài khóa học)

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

Câu trả lời dưới đây mở rộng dựa trên điều này một cách độc đáo.
steampowered

17

nếu bạn muốn thêm các hộp kiểm chưa được chuẩn hóa vào chuỗi truy vấn của mình, hãy thêm phần sau vào hàm gửi jquery của bạn:

var moreinfo = '';

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

Điều này sẽ loại bỏ bất kỳ cơ hội xuống cấp nào cho biểu mẫu của bạn - dữ liệu đã gửi sẽ khác đối với người dùng bị vô hiệu hóa JS.
Andy E

Tôi phải nói nếu bạn sử dụng hàm .serialize () thì đây là giải pháp tốt nhất var data = $ ("# userinput_form"). Serialize (); $ ('# userinput_form input [type = checkbox]: not (: check)'). each (function () {data + = '&' + this.name + '= 0';});
windmaomao

5

jQuery serialize lấy thuộc tính giá trị của đầu vào.

Bây giờ làm thế nào để hộp kiểm và nút radio hoạt động? Nếu bạn đặt sự kiện nhấp chuột của hộp kiểm hoặc nút radio 0 hoặc 1, bạn sẽ có thể thấy các thay đổi.

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

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

và cũng có khi bạn muốn đặt hộp kiểm với trạng thái đã chọn, ví dụ như php

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

2
Mã này không hoạt động. Về cơ bản, nó làm cho điều khiển hộp kiểm trông giống như một đầu vào bình thường (loại texthoặc a select) cho serialize()hàm bằng cách cấp cho hộp kiểm một thuộc valuetính - luôn đồng bộ với trạng thái đã chọn. Và nó thanh lịch hơn câu trả lời đã chọn.
Annabel

đối với .Net MVC, việc sử dụng các giá trị True và False sẽ cho phép phép ánh xạ mô hình mvc thiết lập thuộc tính mô hình Boolean của bạn. Và thêm các thuộc tính này vào <input> của bạn để hiển thị chế độ xem phù hợp: value = "@ (Model.Item2.IsCurrent?" True ":" False ")" @ (Model.Item2.IsCurrent? "Cked = 'đã kiểm tra' " : "")
DavidCC

4

Đây là một giải pháp khác mở rộng phương thức "serializeArray" (trong khi vẫn giữ nguyên trạng thái ban đầu).

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

Điều này thực sự sẽ thêm các kết quả boolean "true" hoặc "false", nhưng nếu muốn, bạn có thể sử dụng "1" và "0" tương ứng, bằng cách thay đổi giá trị thành value: $item.is(":checked") ? 1 : 0.

Sử dụng

Như thường lệ, hãy gọi phương thức trên biểu mẫu của bạn: $form.serialize()hoặc $form.serializeArray(). Điều gì xảy ra là serializetận dụng mọi thứ serializeArray, vì vậy bạn sẽ nhận được kết quả thích hợp (mặc dù định dạng khác nhau) với bất kỳ phương thức nào bạn gọi.


LỖI: Thật tệ, khi hộp kiểm là "true", nó vẫn sẽ nối thêm một tham số với giá trị 'on' thông thường. Sẽ sửa lỗi này ...
bigp

nếu hộp kiểm được chọn, bạn sẽ nhận được 2 giá trị có cùng tên trong kết quả ... một giá trị có 'on' và một giá trị bạn thêm vào cuối bằng '1' ...
WonderLand 26/10/17

Tôi đã khắc phục sự cố :)
wonderland

4

Bạn có thể gọi handleInputs()add trong hàm gửi của mình trước ajax

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

Nó đang hoạt động hoàn hảo


3

Một kỹ thuật tôi đã sử dụng trong hệ thống của riêng mình và tôi tin rằng được Struts sử dụng, là bao gồm ...

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

... ngay bên cạnh hộp kiểm như một phần của logic tạo biểu mẫu của tôi.

Điều này cho phép tôi xây dựng lại những hộp kiểm nào đã được phân phát trong biểu mẫu nhưng không được chọn, với một chút logic bổ sung để thực hiện khác biệt những gì đã được phân phối và những gì đã được chọn, bạn có những hộp kiểm chưa được chọn. Nội dung gửi cũng giống nhau, bất kể bạn đang sử dụng HTML hay AJAX.

Tùy thuộc vào công nghệ bạn đang sử dụng phía máy chủ, bạn có thể muốn sử dụng cú pháp này ...

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

... để dễ dàng lấy các giá trị này dưới dạng danh sách.


3

Đối với ASP.NET MVC , chúng tôi lưu thành công một biểu mẫu có hộp kiểm qua AJAX POST với nội dung sau, là sự kết hợp của một số phương pháp được tham chiếu trong bài đăng này, bao gồm đề xuất @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

Một lý do để sử dụng tuần tự hóa hộp kiểm không chuẩn không được đề cập trong câu hỏi hoặc trong các câu trả lời hiện tại là chỉ giải mã hóa (thay đổi) các trường đã được chỉ định rõ ràng trong dữ liệu tuần tự hóa - ví dụ: khi bạn đang sử dụng tuần tự hóa jquery và giải mã hóa để / từ một cookie để lưu và tải các tùy chọn.

Thomas Danemar đã thực hiện một sửa đổi đối với serialize()phương pháp tiêu chuẩn để có một checkboxesAsBoolstùy chọn: http://tdanemar.wordpress.com/2010/08/24/jquery-serialize-method-and-checkboxes/ - điều này tương tự như triển khai được liệt kê ở trên bởi @mydoghasworms, nhưng cũng được tích hợp vào tuần tự hóa tiêu chuẩn.

Tôi đã sao chép nó vào Github trong trường hợp bất kỳ ai có cải tiến cần thực hiện tại bất kỳ thời điểm nào: https://gist.github.com/1572512

Ngoài ra, plugin "jquery.deserialize" giờ đây sẽ giải thích chính xác các giá trị hộp kiểm được tuần tự hóa checkboxesAsBoolsvà bỏ qua các hộp kiểm không được đề cập trong dữ liệu được tuần tự hóa: 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
Bạn có thể giải thích câu trả lời của bạn ở tất cả?
Ben,

Câu trả lời này sửa đổi hộp kiểm thành một trường ẩn, vì vậy nó có thể được tuần tự hóa. Câu trả lời này làm cho biểu mẫu được sử dụng một lần vì việc sửa đổi được thực hiện đối với DOM.
Grant

2

Bí quyết là chặn bài đăng biểu mẫu và thay đổi các hộp kiểm thành các trường nhập ẩn.

Ví dụ: Gửi đơn thuần

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

Ví dụ: AJAX

Bạn cần chuyển qua một vài vòng nữa nếu bạn đang đăng biểu mẫu qua ajax để không cập nhật giao diện người dùng.

$('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

Điều này sẽ đặt các giá trị hộp kiểm biểu mẫu của bạn thành boolean bằng cách sử dụng trạng thái đã chọn của chúng.

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

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

Khung mà chúng tôi sử dụng tạo ra hai đầu vào có cùng tên, dẫn đến hành vi không mong muốn khi tuần tự hóa biểu mẫu. Tôi sẽ nhận được mỗi giá trị hộp kiểm được phân tích cú pháp thành một mảng hai phần tử với các giá trị chuỗi. Tùy thuộc vào cách bạn lập bản đồ dữ liệu phía máy chủ, bạn có thể nhận được kết quả không mong muốn.


1
serializeObject () dường như là một plugin jQuery: plugins.jquery.com/serializeObject
iCode

Có một thông tin rất nhỏ serializeObject(): benalman.com/projects/jquery-misc-plugins/#serializeobject
Bernhard Döbler

1

Sử dụng các trường được chọn theo đề xuất của Andy không nhất thiết là lựa chọn tốt nhất cho trải nghiệm người dùng vì nó cần hai lần nhấp chuột thay vì một lần.

Hơn nữa, "Chọn" sử dụng nhiều không gian hơn trong giao diện người dùng so với hộp kiểm.

Câu trả lời của Ash là một giải pháp đơn giản nhưng không hoạt động trong trường hợp các trường mảng .

Trong ngữ cảnh của tôi, tôi có một biểu mẫu có độ dài thay đổi, chứa các hàng hiển thị kết hợp các trường văn bản và hộp kiểm:

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

Để giải mã dữ liệu đã đăng, đơn đặt hàng của các phần tử mảng rất quan trọng. Việc chỉ thêm các mục không được kiểm tra vào một tuần tự hóa Jquery thông thường sẽ không giữ thứ tự của các phần tử hàng.

Đây là một giải pháp được đề xuất dựa trên câu trả lời của Ash:

(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

Tôi đã gặp sự cố tương tự và sự cố sau đây cho phép tôi thu thập tất cả các giá trị đầu vào của biểu mẫu và các hộp kiểm đã chọn / bỏ chọn.

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

"this. $" dành riêng cho khung ứng dụng Zendesk mà tôi đang làm việc cho giải pháp này.
wooz 16

1

Ví dụ này giả định rằng bạn muốn đăng lại một biểu mẫu qua serializevà không serializeArrayvà hộp kiểm không được chọn có nghĩa là 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);

Tôi thích not(:checked)chọn
Bernhard Döbler

1

Đối với những người sử dụng serialize()chức năng:

(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

đôi khi không được chọn có nghĩa là các giá trị khác, ví dụ được chọn có thể có nghĩa là có không được chọn không hoặc 0,1, v.v. nó phụ thuộc vào ý nghĩa bạn muốn đưa ra .. vì vậy có thể là một trạng thái khác bên cạnh "không được chọn có nghĩa là nó không có trong chuỗi truy vấn"

"Nó sẽ giúp việc lưu trữ thông tin trong DB dễ dàng hơn rất nhiều. Bởi vì khi đó số lượng trường từ Serialize sẽ bằng với số trường trong bảng. Bây giờ tôi phải sắp xếp lại những trường nào còn thiếu", bạn nói đúng, đây cũng là vấn đề của tôi. .. vì vậy có vẻ như tôi phải kiểm tra giá trị không tồn tại này ....

nhưng có lẽ đây có thể là một giải pháp? http://tdanemar.wordpress.com/2010/08/24/jquery-serialize-method-and-checkboxes/


1
Nếu sự không tồn tại gây ra sự cố, bạn nên sử dụng <select>tùy chọn có / không có, thay vì tạo thứ gì đó đi ngược lại cách đặc tả HTML xác định biểu mẫu sẽ được gửi.
Andy E

0

chỉ cần thêm một đầu vào ẩn

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

không cần giá trị, tôi đã thử nghiệm điều này phù hợp với tôi


1
Hãy làm sáng tỏ. Cố gắng thêm các ví dụ mã và có thể liên kết đến tài liệu.
Yotam Omer

0

Bạn có thể nhận giá trị đầu vào với tuần tự hóa 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

Chỉ để mở rộng (các) câu trả lời ở trên, trong trường hợp của tôi, tôi yêu cầu gửi câu trả lời có / không đối với một ID duy nhất được tuần tự hóa cho phần bắt phụ trợ của tôi.

Tôi đặt các phần tử hộp kiểm để chứa ID của một cột cơ sở dữ liệu cụ thể, còn gọi là (được chọn mặc định) :

(Lưỡi dao Laravel)

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

Khi tôi gửi, tôi lấy dữ liệu bằng:

(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

Tôi đã sử dụng cách này và nhận được các giá trị "0" hoặc nếu được chọn "1". Điều này nói lên rằng nếu tên đầu vào hộp kiểm không tồn tại trong tuần tự hóa form_datathì nó có nghĩa là nó không được kiểm tra, sau đó thêm giá trị bằng không ( form_data += '&' + name + '=0'), nhưng nếu được kiểm tra serialize()hàm sẽ tự động thêm nó.

   /*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

Thử cái này:

$ (': input [type = "checkbox"]: check'). map (function () {return this.value}). get ();


-1

Tôi đăng giải pháp đã làm việc cho tôi!

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"}]"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.