asp.net mvc: Html.CheckBox एक अतिरिक्त छिपा इनपुट क्यों उत्पन्न कर रहा है


215

मैंने अभी देखा कि Html.CheckBox("foo")एक के बजाय 2 इनपुट उत्पन्न करता है, किसी को भी पता है कि ऐसा क्यों है?

<input id="foo" name="foo" type="checkbox" value="true" />
<input name="foo" type="hidden" value="false" /> 


1
संभावित डुप्लिकेट प्रश्न में ericvg का उत्तर यह भी बताता है कि चेकबॉक्स और छिपे हुए फ़ील्ड को सबमिट करने पर मॉडल बाइंडर क्या करता है।
थियोफिलस

1
मुझे इस बात से नफरत है कि यह मेरे jquery के साथ मालिश कर रहा था।
जेरी लियांग

2
पीवीसी द्वारा अजीब कार्यान्वयन। दोनों मानों को भेजना समझ में नहीं आता है। मैंने Request.From ["myCheckBox"] की जाँच की और इसका मूल्य सही, गलत था। WTF। मुझे नियंत्रण को मैन्युअल रूप से दृश्य में लिखना था।
निक मसाओ

यदि यह वास्तव में अवांछित है, तो Html.CheckBox (...) का उपयोग न करें और एक चेकबॉक्स के लिए बस HTML इनपुट करें
wnbates

जवाबों:


197

यदि चेकबॉक्स चयनित नहीं है, तो फ़ॉर्म फ़ील्ड सबमिट नहीं की जाती है। यही कारण है कि छिपे हुए क्षेत्र में हमेशा गलत मूल्य होता है। यदि आप चेकबॉक्स को अनियंत्रित छोड़ देते हैं, तो फॉर्म में छिपे हुए फ़ील्ड से मूल्य होगा। इस प्रकार ASP.NET MVC चेकबॉक्स मानों को संभालता है।

यदि आप इस बात की पुष्टि करना चाहते हैं, तो Html.Hidden के साथ नहीं बल्कि फ़ॉर्म पर एक चेकबॉक्स रखें <input type="checkbox" name="MyTestCheckboxValue"></input>। चेकबॉक्स अनियंत्रित छोड़ दें, फ़ॉर्म सबमिट करें और सर्वर साइड पर पोस्ट किए गए अनुरोध मानों को देखें। आप देखेंगे कि कोई चेकबॉक्स मान नहीं है। यदि आपके पास छिपी हुई फ़ील्ड है, तो इसमें मूल्य के MyTestCheckboxValueसाथ प्रविष्टि होगी false


52
यदि आपने बॉक्स की जांच नहीं की है, तो जाहिर है कि उत्तर गलत है, आइटम को वापस भेजने के लिए इसकी कोई आवश्यकता नहीं है। मेरी राय में मूर्खतापूर्ण डिजाइन।
मफिन मैन

54
@ TheMuffinMan: यह मूर्खतापूर्ण विकल्प नहीं है। कहते हैं कि आपके व्यू मॉडल में प्रॉपर्टी है IsActive, जिसे trueकंस्ट्रक्टर में शुरू किया गया है। उपयोगकर्ता चेकबॉक्स को अचयनित करता है, लेकिन चूंकि मान सर्वर पर नहीं भेजा जाता है, इसलिए मॉडल बाइंडर इसे नहीं उठाता है, और संपत्ति मान नहीं बदला जाता है। मॉडल बाइंडर को यह नहीं मान लेना चाहिए कि यदि मूल्य नहीं भेजा गया है, तो इसे गलत पर सेट किया गया था, क्योंकि यह इस मूल्य को नहीं भेजने का आपका निर्णय हो सकता है।
लुकलेड

21
यह एक हानिरहित चेकबॉक्स से शुरू होता है और फिर इससे पहले कि आप जानते हैं कि हमारे पास दृश्य स्थिति है तो यह ASP.NET MVCForms में विकसित होता है।
मफिन मैन

4
@LukLed ने आपकी टिप्पणी का उत्तर देर से दिया ... मुझे लगता है कि तर्क त्रुटिपूर्ण है क्योंकि यदि आपके दृश्य मॉडल में कोई गुण प्रकार int है और प्रपत्र पर कोई इनपुट नहीं है, तो डिफ़ॉल्ट मान 0 है क्योंकि इसे बदलने के लिए कोई मान नहीं आया था। वही किसी भी अन्य संपत्ति के साथ जाता है, एक स्ट्रिंग के लिए डिफ़ॉल्ट मान शून्य है। यदि आप एक मूल्य नहीं भेजते हैं तो यह अशक्त है। निर्माता को सही में संपत्ति सेट करने के आपके उदाहरण में, यह ईमानदारी से एक खराब डिजाइन निर्णय है और यह अब सामने आता है कि HTTP भूमि में चेकबॉक्स कैसे काम करते हैं।
मफिन मैन

8
विकलांग चेकबॉक्स के लिए यह छायांकन तर्क टूट जाता है - वे चेक किए जाने पर falseभी मूल्य भेजते हैं, और यह भ्रामक है। यदि ASP.NET डिफ़ॉल्ट HTTP व्यवहार के साथ संगत होना चाहता है, तो अक्षम चेकबॉक्स को कोई भी मूल्य नहीं भेजना चाहिए।
जस्टअमार्टिन

31

छिपे हुए इनपुट को जोड़ने से रोकने के लिए आप एक सहायक लिख सकते हैं:

using System.Web.Mvc;
using System.Web.Mvc.Html;

public static class HelperUI
{
    public static MvcHtmlString CheckBoxSimple(this HtmlHelper htmlHelper, string name, object htmlAttributes)
    {
        string checkBoxWithHidden = htmlHelper.CheckBox(name, htmlAttributes).ToHtmlString().Trim();
        string pureCheckBox = checkBoxWithHidden.Substring(0, checkBoxWithHidden.IndexOf("<input", 1));
        return new MvcHtmlString(pureCheckBox);
    }
}

इसका इस्तेमाल करें:

@Html.CheckBoxSimple("foo", new {value = bar.Id})

4
इसने मुझे केवल एक मिनट के लिए @using Your.Name.Spaceउलझा दिया है ... यदि आपका सहायक किसी नेमस्पेस में है तो अपने .cshtml रेजर व्यू फाइल के शीर्ष पर जोड़ना न भूलें ।
ooXei1sh

3
@ ooXei1sh या तो, या सभी नामों System.Web.Mvc.Htmlपर सुलभ होने के लिए अपने सहायक को नाम स्थान में रखें
ल्यूक

1
यदि आप इसे फॉर्म पोस्टबैक के लिए उपयोग करना चाहते हैं या फॉर्म वैल्यू के साथ अजाक्स के माध्यम से पोस्ट करना चाहते हैं, तो आपको चेकबॉक्स पर ऑन्चेंज इवेंट के माध्यम से मान को सही या गलत पर सेट करने की आवश्यकता होगी। @ Html.CheckBoxSimple (x => Model.Foo, new {value = Model.Foo, onchange = "toggleCheck (यह)"})। फिर जावास्क्रिप्ट फंक्शन में ToggleCompleted (el) {var check = $ (el) .is (': check' '); $ ( '# फू') वैल (चयनित)। }
जॉन 81१

12

जब चेक बॉक्स की जाँच की जाती है और इसे प्रस्तुत किया जाता है

if ($('[name="foo"]:checked').length > 0)
    $('[name="foo"]:hidden').val(true);

देखें


8

मैनुअल दृष्टिकोण यह है:

bool IsDefault = (Request.Form["IsDefault"] != "false");

1
और क्या यह आपको चेकबॉक्स प्रकार मान प्राप्त करने की गारंटी है और छिपे हुए प्रकार का मूल्य नहीं?
ब्रायन स्वीनी

1
यह अप्रासंगिक है। जब चेकबॉक्स को चेक नहीं किया जाता है, तो यह पोस्ट नहीं करता है। तो छिपे हुए बॉक्स में 'गलत' होगा। यदि चेकबॉक्स की जाँच की जाती है कि 'सत्य, सत्य' का मान लौटाया गया है (मुझे लगता है), और यह 'असत्य' के बराबर नहीं है।
वलमास

16
नहीं, जब चेकबॉक्स की जाँच की जाती है, तो सही और गलत दोनों पोस्ट किए जाते हैं क्योंकि चेकबॉक्स और छिपे हुए फ़ील्ड दोनों को वापस भेजे जाने के लिए वैध नियंत्रण हैं। Mvc बाइंडर तब जांचता है कि क्या किसी दिए गए नामवे के लिए सही मूल्य मौजूद है और यदि ऐसा है तो यह सही मूल्य पसंद करता है। आप पोस्ट किए गए डेटा को देखकर इसकी जांच कर सकते हैं। इसमें एकल नाम के विरुद्ध सही और गलत दोनों तरह के मूल्य होंगे।
ZafarYousafi

यह मुझे एक बार मिला, मैं जाँच रहा था कि क्या मूल्य == सच
टेरी कर्नन

8

यह अलेक्जेंडर ट्रोफिमोव के समाधान का दृढ़ता से टाइप किया गया संस्करण है:

using System.Web.Mvc;
using System.Web.Mvc.Html;

public static class HelperUI
{
    public static MvcHtmlString CheckBoxSimpleFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool>> expression, object htmlAttributes)
    {
        string checkBoxWithHidden = htmlHelper.CheckBoxFor(expression, htmlAttributes).ToHtmlString().Trim();
        string pureCheckBox = checkBoxWithHidden.Substring(0, checkBoxWithHidden.IndexOf("<input", 1));
        return new MvcHtmlString(pureCheckBox);
    }
}

4

युक्तियों का उपयोग करें, यह दो संभावित पोस्ट मानों के साथ काम करेगा: "झूठे" या "सच्चे, झूठे"।

bool isChecked = Request.Form["foo"].Contains("true");

1

छिपे हुए इनपुट स्टाइल चेकबॉक्स के साथ समस्याएं पैदा कर रहे थे। इसलिए मैंने चेकबॉक्स वाले डिव के बाहर छिपे इनपुट को रखने के लिए एक एचटीएमएल हेल्पर एक्सटेंशन बनाया।

using System;
using System.Linq.Expressions;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;

namespace YourNameSpace
{
    public static class HtmlHelperExtensions
    {
        public static MvcHtmlString CustomCheckBoxFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression, string labelText)
        {
            //get the data from the model binding
            var fieldName = ExpressionHelper.GetExpressionText(expression);
            var fullBindingName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName);
            var fieldId = TagBuilder.CreateSanitizedId(fullBindingName);
            var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            var modelValue = metaData.Model;

            //create the checkbox
            TagBuilder checkbox = new TagBuilder("input");
            checkbox.MergeAttribute("type", "checkbox");
            checkbox.MergeAttribute("value", "true"); //the visible checkbox must always have true
            checkbox.MergeAttribute("name", fullBindingName);
            checkbox.MergeAttribute("id", fieldId);

            //is the checkbox checked
            bool isChecked = false;
            if (modelValue != null)
            {
                bool.TryParse(modelValue.ToString(), out isChecked);
            }
            if (isChecked)
            {
                checkbox.MergeAttribute("checked", "checked");
            }

            //add the validation
            checkbox.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(fieldId, metaData));

            //create the outer div
            var outerDiv = new TagBuilder("div");
            outerDiv.AddCssClass("checkbox-container");

            //create the label in the outer div
            var label = new TagBuilder("label");
            label.MergeAttribute("for", fieldId);
            label.AddCssClass("checkbox");

            //render the control
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(outerDiv.ToString(TagRenderMode.StartTag));
            sb.AppendLine(checkbox.ToString(TagRenderMode.SelfClosing));
            sb.AppendLine(label.ToString(TagRenderMode.StartTag));
            sb.AppendLine(labelText); //the label
            sb.AppendLine("<svg width=\"10\" height=\"10\" class=\"icon-check\"><use xlink:href=\"/icons.svg#check\"></use></svg>"); //optional icon
            sb.AppendLine(label.ToString(TagRenderMode.EndTag));
            sb.AppendLine(outerDiv.ToString(TagRenderMode.EndTag));

            //create the extra hidden input needed by MVC outside the div
            TagBuilder hiddenCheckbox = new TagBuilder("input");
            hiddenCheckbox.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
            hiddenCheckbox.MergeAttribute("name", fullBindingName);
            hiddenCheckbox.MergeAttribute("value", "false");
            sb.Append(hiddenCheckbox.ToString(TagRenderMode.SelfClosing));

            //return the custom checkbox
            return MvcHtmlString.Create(sb.ToString());
        }

परिणाम

<div class="checkbox-container">
    <input checked="checked" id="Model_myCheckBox" name="Model.myCheckBox" type="checkbox" value="true">
    <label class="checkbox" for="Model_myCheckBox">
        The checkbox label
        <svg width="10" height="10" class="icon-check"><use xlink:href="/icons.svg#check"></use></svg>
    </label>
</div>
<input name="Model.myCheckBox" type="hidden" value="false">

0

यह एक बग नहीं है! सर्वर पर फ़ॉर्म को पोस्ट करने के बाद, यह हमेशा एक मान होने की संभावना जोड़ता है। यदि आप jQuery के साथ चेकबॉक्स इनपुट फ़ील्ड से निपटना चाहते हैं, तो प्रोप विधि (पैरामीटर के रूप में 'चेक की गई संपत्ति को पास करें) का उपयोग करें। उदाहरण:$('#id').prop('checked')


0

आप अपने मॉडल के निर्माता को इनिशियलाइज़ करने की कोशिश कर सकते हैं जैसे:

public MemberFormModel() {
    foo = true;
}

और आपके विचार में:

@html.Checkbox(...)
@html.Hidden(...)

0

मैंने पाया कि जब मैं एक वेबग्रिड था, तो यह वास्तव में समस्या का कारण बना। WebGrid पर सॉर्टिंग लिंक दोगुनी हो जाती है या फिर x = true और x = false से x = true में गलत हो जाता है, जिसके लिए चेकबॉक्स में पार्स त्रुटि होती है।

मैंने क्लाइंट पक्ष पर छिपे हुए फ़ील्ड को हटाने के लिए jQuery का उपयोग किया:

    <script type="text/javascript">
    $(function () {
        // delete extra hidden fields created by checkboxes as the grid links mess this up by doubling the querystring parameters
        $("input[type='hidden'][name='x']").remove();
    });
    </script>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.