繁体   English   中英

HTML 表单只读 SELECT 标记/输入

[英]HTML form readonly SELECT tag/input

根据 HTML 规范,HTML 中的select标签没有readonly属性,只有disabled属性。 因此,如果您想阻止用户更改下拉菜单,则必须使用disabled

唯一的问题是禁用的 HTML 表单输入不会包含在 POST / GET 数据中。

模拟select标签的readonly属性并仍然获取 POST 数据的最佳方法是什么?

您应该disabled select元素,但还应添加另一个具有相同名称和值的隐藏input

如果重新启用 SELECT,则应将其值复制到 onchange 事件中的隐藏输入并禁用(或删除)隐藏输入。

这是一个演示:

 $('#mainform').submit(function() { $('#formdata_container').show(); $('#formdata').html($(this).serialize()); return false; }); $('#enableselect').click(function() { $('#mainform input[name=animal]') .attr("disabled", true); $('#animal-select') .attr('disabled', false) .attr('name', 'animal'); $('#enableselect').hide(); return false; });
 #formdata_container { padding: 10px; }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div> <form id="mainform"> <select id="animal-select" disabled="true"> <option value="cat" selected>Cat</option> <option value="dog">Dog</option> <option value="hamster">Hamster</option> </select> <input type="hidden" name="animal" value="cat"/> <button id="enableselect">Enable</button> <select name="color"> <option value="blue" selected>Blue</option> <option value="green">Green</option> <option value="red">Red</option> </select> <input type="submit"/> </form> </div> <div id="formdata_container" style="display:none"> <div>Submitted data:</div> <div id="formdata"> </div> </div>

我们还可以禁用除选定选项之外的所有选项。

这样下拉菜单仍然有效(并提交其值),但用户无法选择另一个值。

演示

 <select> <option disabled>1</option> <option selected>2</option> <option disabled>3</option> </select>

您可以在提交时重新启用选择对象。

编辑:即,通常禁用选择标签(使用 disabled 属性),然后在提交表单之前自动重新启用它:

jQuery 示例:

  • 要禁用它:

     $('#yourSelect').prop('disabled', true);
  • 要在提交之前重新启用它,以便包含 GET / POST 数据:

     $('#yourForm').on('submit', function() { $('#yourSelect').prop('disabled', false); });

此外,您可以重新启用每个禁用的输入或选择:

$('#yourForm').on('submit', function() {
    $('input, select').prop('disabled', false);
});

select元素执行readOnly属性的另一种方法是使用css

你可以这样做:

$('#selection').css('pointer-events','none');

演示

简单的 jQuery 解决方案

如果您的选择具有readonly类,请使用此选项

jQuery('select.readonly option:not(:selected)').attr('disabled',true);

或者,如果您的选择具有readonly="readonly"属性

$('select[readonly="readonly"] option:not(:selected)').attr('disabled',true);
<select id="countries" onfocus="this.defaultIndex=this.selectedIndex;" onchange="this.selectedIndex=this.defaultIndex;">
<option value="1">Country1</option>
<option value="2">Country2</option>
<option value="3">Country3</option>
<option value="4">Country4</option>
<option value="5">Country5</option>
<option value="6">Country6</option>
<option value="7" selected="selected">Country7</option>
<option value="8">Country8</option>
<option value="9">Country9</option>
</select>

在 IE 6、7 和 8b2、Firefox 2 和 3、Opera 9.62、Safari 3.2.1 for Windows 和 Google Chrome 中测试和工作。

我知道为时已晚,但可以使用简单的 CSS 来完成:

select[readonly] option, select[readonly] optgroup {
    display: none;
}

The style hides all the options and the groups when the select is in readonly state, so the user can not change his selection.

不需要 JavaScript hack。

简单的 CSS 解决方案:

select[readonly]{
    background: #eee;
    cursor:no-drop;
}

select[readonly] option{
    display:none;
}

这导致选择为灰色,悬停时带有漂亮的“禁用”光标
并且在选择选项列表时为“空”,因此您无法更改其值。

这是我找到的最佳解决方案:

$("#YourSELECTIdHere option:not(:selected)").prop("disabled", true);

上面的代码禁用所有其他未选中的选项,同时保持选中的选项处于启用状态。 这样做,选定的选项将使其成为回发数据。

另一个更现代的选项(不是双关语)是禁用选择元素的所有选项,而不是所选元素。

但是请注意,这是 HTML 4.0 功能,即 6、7、8 beta 1 似乎不尊重这一点。

http://www.gtalbot.org/BrowserBugsSection/MSIE7Bugs/OptionDisabledSupport.html

更简单:将样式属性添加到您的选择标签:

style="pointer-events: none;"

派对有点晚了。 但这对我来说似乎完美无缺

select[readonly] {
    pointer-events:none;
}

除了禁用不应该选择的选项之外,我还想让它们从列表中消失,但如果我以后需要,仍然可以启用它们:

$("select[readonly]").find("option:not(:selected)").hide().attr("disabled",true);

这会找到所有具有 readonly 属性的选择元素,然后在那些未选择的选择中找到所有选项,然后隐藏它们并禁用它们。

出于性能原因将jquery查询分开2很重要,因为jquery从右到左读取它们,代码:

$("select[readonly] option:not(:selected)")

将首先在文档中找到所有未选择的选项,然后使用 readonly 属性过滤选择中的选项。

这是最简单和最好的解决方案。 您将在您的选择上设置一个 readolny 属性,或任何其他属性,如 data-readonly,并执行以下操作

$("select[readonly]").live("focus mousedown mouseup click",function(e){
    e.preventDefault();
    e.stopPropagation();
});

如果您禁用表单字段,则在提交表单时不会发送该字段。 因此,如果您需要一个类似于disabled但发送值的readonly ,请执行以下操作:

在元素的只读属性发生任何更改之后。

$('select.readonly option:not(:selected)').attr('disabled',true);

$('select:not([readonly]) option').removeAttr('disabled');

使用 tabindex 的解决方案。 适用于选择但也适用于文本输入。

只需使用 .disabled 类。

CSS:

.disabled {
    pointer-events:none; /* No cursor */
    background-color: #eee; /* Gray background */
}

JS:

$(".disabled").attr("tabindex", "-1");

HTML:

<select class="disabled">
    <option value="0">0</option>
</select>

<input type="text" class="disabled" />

编辑:使用 Internet Explorer,您还需要这个 JS:

$(document).on("mousedown", ".disabled", function (e) {
    e.preventDefault();
});

当您计划将选择禁用时设置为只读,然后在提交表单之前删除禁用属性。

// global variable to store original event/handler for save button
var form_save_button_func = null;

// function to get jQuery object for save button
function get_form_button_by_id(button_id) {
    return jQuery("input[type=button]#"+button_id);
}

// alter value of disabled element
function set_disabled_elem_value(elem_id, value)  {
    jQuery("#"+elem_id).removeAttr("disabled");
    jQuery("#"+elem_id).val(value);
    jQuery("#"+elem_id).attr('disabled','disabled');
}

function set_form_bottom_button_save_custom_code_generic(msg) {
    // save original event/handler that was either declared
    // through javascript or html onclick attribute
    // in a global variable
    form_save_button_func = get_form_button_by_id('BtnSave').prop('onclick'); // jQuery 1.6
    //form_save_button_func = get_form_button_by_id('BtnSave').prop('onclick'); // jQuery 1.7

    // unbind original event/handler (can use any of following statements below)
    get_form_button_by_value('BtnSave').unbind('click');
    get_form_button_by_value('BtnSave').removeAttr('onclick');

    // alternate save code which also calls original event/handler stored in global variable
    get_form_button_by_value('BtnSave').click(function(event){
        event.preventDefault();
        var confirm_result = confirm(msg);
        if (confirm_result) {
            if (jQuery("form.anyForm").find('input[type=text], textarea, select').filter(".disabled-form-elem").length > 0) {
                jQuery("form.anyForm").find('input[type=text], textarea, select').filter(".disabled-form-elem").removeAttr("disabled");
            }

            // disallow further editing of fields once save operation is underway
            // by making them readonly
            // you can also disallow form editing by showing a large transparent
            // div over form such as loading animation with "Saving" message text
            jQuery("form.anyForm").find('input[type=text], textarea, select').attr('ReadOnly','True');

            // now execute original event/handler
            form_save_button_func();
        }
    });
}

$(document).ready(function() {
    // if you want to define save button code in javascript then define it now

    // code below for record update
    set_form_bottom_button_save_custom_code_generic("Do you really want to update this record?");
    // code below for new record
    //set_form_bottom_button_save_custom_code_generic("Do you really want to create this new record?");

    // start disabling elements on form load by also adding a class to identify disabled elements
    jQuery("input[type=text]#phone").addClass('disabled-form-elem').attr('disabled','disabled');
    jQuery("input[type=text]#fax").addClass('disabled-form-elem').attr('disabled','disabled');
    jQuery("select#country").addClass('disabled-form-elem').attr('disabled','disabled');
    jQuery("textarea#address").addClass('disabled-form-elem').attr('disabled','disabled');

    set_disabled_elem_value('phone', '123121231');
    set_disabled_elem_value('fax', '123123123');
    set_disabled_elem_value('country', 'Pakistan');
    set_disabled_elem_value('address', 'address');

}); // end of $(document).ready function

一种简单的服务器端方法是删除除您要选择的选项之外的所有选项。 因此,在 Zend Framework 1.12 中,如果 $element 是 Zend_Form_Element_Select:

 $value =  $element->getValue();
 $options = $element->getAttrib('options');
 $sole_option = array($value => $options[$value]);
 $element->setAttrib('options', $sole_option);

[最简单的解决方案]

由于 OP 特别要求他不想禁用 select 元素,这就是我用来使 select readonly

在 html 中

<select class="form-control-sm"  style="pointer-events: none;" onclick="return false;" onkeydown="return false;" ></select>

而已

或者如果你想通过 javascript

 let isReadOnly = true ; selectElement.onclick = function () { return !isReadOnly ; }; selectElement.onkeydown =function(){ return !isReadOnly ; } ; selectElement.style.pointerEvents = isReadOnly ? "none" : "all" ;

解释

  • 将指针事件设置为无会禁用使用鼠标/光标事件编辑“选择元素”
  • 将 onclick 和 onkeydown 函数设置为返回 false 禁用使用键盘编辑“选择元素”

这样您就不必创建任何额外的元素,或使用 javascript 禁用/重新启用该元素或弄乱表单提交逻辑,或使用任何第三方库。

另外,您可以轻松添加 css 样式,例如将背景颜色设置为灰色或将文本颜色设置为灰色,以暗示该元素是只读的。 我没有将它添加到代码中,因为这非常特定于您的站点主题

如果您使用的是 jquery validate,您可以执行以下操作,我使用 disabled 属性没有问题:

$(function(){
    $('#myform').validate({
        submitHandler:function(form){
            $('select').removeAttr('disabled');
            form.submit();
        }
    });
});

遵循格兰特瓦格纳的建议; 这是一个使用处理函数而不是直接 onXXX 属性的 jQuery 片段:

var readonlySelect = function(selector, makeReadonly) {

    $(selector).filter("select").each(function(i){
        var select = $(this);

        //remove any existing readonly handler
        if(this.readonlyFn) select.unbind("change", this.readonlyFn);
        if(this.readonlyIndex) this.readonlyIndex = null;

        if(makeReadonly) {
            this.readonlyIndex = this.selectedIndex;
            this.readonlyFn = function(){
                this.selectedIndex = this.readonlyIndex;
            };
            select.bind("change", this.readonlyFn);
        }
    });

};

我发现使用纯 javascript(即:不需要 JQuery 库)效果很好,是将<select>标记的 innerHTML 更改为所需的单个剩余值。

前:

<select name='day' id='day'>
  <option>SUN</option>
  <option>MON</option>
  <option>TUE</option>
  <option>WED</option>
  <option>THU</option>
  <option>FRI</option>
  <option>SAT</option>
</select>

示例 Javascript:

document.getElementById('day').innerHTML = '<option>FRI</option>';

后:

<select name='day' id='day'>
  <option>FRI</option>
</select>

这样,视觉效果不会改变,这将在<FORM>中发布/获取。

input是您的<select>元素:

input.querySelectorAll(':not([selected])').forEach(option => {
  option.disabled = true
})

这将保留数据中的选择(因为它没有被禁用),并且只有未选择的option被禁用,因此不可选择。 结果是无法更改的可读选择(=> 只读)。

我用jquery解决了它:

      $("select.myselect").bind("focus", function(){
        if($(this).hasClass('readonly'))
        {
          $(this).blur();   
          return;
        }
      });

简单地说,在提交表单之前删除 disabled 属性。

    $('form').submit(function () {
        $("#Id_Unidade").attr("disabled", false);
    });
<select id="case_reason" name="case_reason" disabled="disabled">

disabled="disabled" ->将从数据库中获取您的值并在表单中显示它。 readonly="readonly" ->您可以在选择框中更改您的值,但您的值无法保存在您的数据库中。

除了选择本身,您可以禁用除当前选择的选项之外的所有选项。 这给出了一个工作下拉列表的外观,但只有您想要传入的选项才是有效的选择。

如果选择下拉菜单自出生以来就是只读的并且根本不需要更改,也许您应该使用另一个控件来代替? 像一个简单的<div> (加上隐藏的表单域)或一个<input type="text">

补充:如果下拉菜单不是一直只读的并且使用 JavaScript 来启用/禁用它,那么这仍然是一个解决方案 - 只需即时修改 DOM。

模拟 select 标签的 readonly 属性并仍然获取 POST 数据的最佳方法是什么?

只需将其设为输入/文本字段并为其添加“只读”属性即可。 如果选择有效地“禁用”,那么您无论如何都无法更改该值,因此您不需要选择标签,您可以简单地将“选定”值显示为只读文本输入。 对于大多数 UI 目的,我认为这应该足够了。

html解决方案:

<select onfocus="this.blur();">

javascript的:

selectElement.addEventListener("focus", selectElement.blur, true); selectElement.attachEvent("focus", selectElement.blur); //thanks, IE

去除:

selectElement.removeEventListener("focus", selectElement.blur, true); selectElement.detachEvent("focus", selectElement.blur); //thanks, IE

编辑:添加删除方法

在 IE 中,我能够通过双击来击败 o​​nfocus=>onblur 方法。 但是记住这个值然后在 onchange 事件中恢复它似乎可以解决这个问题。

<select onfocus="this.oldvalue=this.value;this.blur();" onchange="this.value=this.oldvalue;">
....
</select>

您可以使用 javascript 变量在没有扩展属性的情况下执行类似操作。

这是使用自定义 jQuery 函数来实现功能的尝试(如此处所述):

$(function(){

 $.prototype.toggleDisable = function(flag) {
    // prepare some values
    var selectId = $(this).attr('id');
    var hiddenId = selectId + 'hidden';
    if (flag) {
      // disable the select - however this will not submit the value of the select
      // a new hidden form element will be created below to compensate for the 
      // non-submitted select value 
      $(this).attr('disabled', true);

      // gather attributes
      var selectVal = $(this).val();
      var selectName = $(this).attr('name');

      // creates a hidden form element to submit the value of the disabled select
      $(this).parents('form').append($('<input></input>').
        attr('type', 'hidden').
        attr('id', hiddenId).
        attr('name', selectName).
        val(selectVal) );
    } else {
      // remove the newly-created hidden form element
      $(this).parents('form').remove(hiddenId);
      // enable back the element
      $(this).removeAttr('disabled');
    }
  }

  // Usage
  // $('#some_select_element').toggleDisable(true);
  // $('#some_select_element').toggleDisable(false);

});
var selectedOpt;//initialize var
    var newIdForHidden;//initialize var
    $('.disabledOnEdit').focusin(function(){
        selectedOpt = $(this).find(":selected").val();
        newIdForHidden = $(this).attr('id')+'Hidden';
        //alert(selectedOpt+','+newIdForHidden);
        $(this).append('');
        $(this).find('input.hiddenSelectedOpt').attr('id',newIdForHidden).val(selectedOpt);
    });
    $('.disabledOnEdit').focusout(function(){
        var oldSelectedValue=$(this).find('input.hiddenSelectedOpt').val();
        $(this).val(oldSelectedValue);
    });

select multiple 对上述代码建议的响应几乎没有。 经过大量的大锤和拼凑,我最终得到了这个:

var thisId="";
var thisVal="";
function selectAll(){
    $("#"+thisId+" option").each(function(){
        if(!$(this).prop("disabled"))$(this).prop("selected",true);
    });
    $("#"+thisId).prop("disabled",false);
}
$(document).ready(function(){
    $("select option:not(:selected)").attr('disabled',true);
    $("select[multiple]").focus(function(){
        thisId=$(this).prop("id");
        thisVal=$(this).val();
        $(this).prop("disabled",true).blur();
        setTimeout("selectAll();",200);
    });
});

很简单。 首先将值存储在变量中。 然后在将事件设置值更改为保存初始值的存储变量时

我有一个名字叫映射。 那么我的代码将如下所示;

$("document").ready(function(){ 
    var mapping=$("select[name=mapping]").val();
    $("select[name=mapping]").change(function(){
        $("select[name=mapping]").val(mapping);
    });
});

如果您有一个应该是只读的选择标签,您必须在逻辑上将选择框转换为单个“文本”字段。

我这样说是合乎逻辑的,因为它就像:“我必须向用户显示一个值”

无论值是否来自选择标签,仍然是单个值并且不能更改(只读)。

因此,从逻辑上讲,只有在第一次插入值时才使用选择标记。

然后,当您需要显示此值时,您必须将其放在“文本字段-只读”上。

如果只读,则成为值列表(选定值)的多选相同

我使用“文本”是因为只读标签不需要“类型”属性。 干杯

我知道这不会帮助所有人(如果您只是客户端),但会帮助一些全栈并控制后端和前端的人。

如果用户没有编辑字段的权限,我只返回下拉列表的当前选择。

这是我的一些后端控制器:

        #region Prepare Action Priviledges
        editAuditVM.ExtAuditEditRoleMatrixVM = new ExtAuditEditRoleMatrixVM
        {
            CanEditAcn = _extAuditEditRoleMatrixHelper.CanEditAcn(user, audit),
            CanEditSensitiveDesignation = _extAuditEditRoleMatrixHelper.CanEditSensitiveDesignation(user, audit),
            CanEditTitle = _extAuditEditRoleMatrixHelper.CanEditTitle(),
            CanEditAuditScope = _extAuditEditRoleMatrixHelper.CanEditAuditScope(user, audit)
        };
        #endregion


        #region Prepare SelectLists for Drop Downs
        #region AuditScope List
        IQueryable<SelectListItem> auditScopes = _auditTypesRepo.AuditTypes
            .Where(at => at.AuditTypeClassCode.ToLower() == "e")
            .Select(at => new SelectListItem
            { Text = at.AuditTypeText, Value = at.AuditTypeID.ToString() });
        // Cannot make a select readonly on client side.
        //  So only return currently selected option.
        if (!editAuditVM.ExtAuditEditRoleMatrixVM.CanEditAuditScope)
        {
            auditScopes = auditScopes
                .Where(ascopeId => ascopeId.Value == editAuditVM.ExternalAudit.AuditTypeID.ToString());
        }
        #endregion
        #endregion

因此,无论出于何种原因,这里提到的所有基于 jquery 的解决方案都不适合我。 所以这是一个纯 javascript 解决方案,它在进行 POST 时也应该保留选定的值。

setDropdownReadOnly('yourIdGoesHere',true/false)
 function setDropdownReadOnly(controlName, state) { var ddl = document.getElementById(controlName); for (i = 0; i < ddl.length; i++) { if (i == ddl.selectedIndex) ddl[i].disabled = false; else ddl[i].disabled = state; } }

我的解决方案是添加select[readonly] { pointer-events: none; } select[readonly] { pointer-events: none; }尽可能多的人在这里建议,然后添加这个 JS 来处理键盘事件:

$(document).on('keydown', 'select[readonly]', function(e) {
    if (e.keyCode != 9) {
        if (e.preventDefault) {
            e.preventDefault();
        }

        e.returnValue = false;
        e.cancel = true;
    }
});

这仍然允许使用制表符遍历元素。

摘自https://stackoverflow.com/a/71086058/18183749

如果您不能使用“禁用”属性(因为它会删除 POST 时的值输入),并注意到 html 属性“只读”仅适用于 textarea 和一些输入(文本、密码、搜索,据我所知) ),最后,如果您不想费心用隐藏的输入逻辑复制所有选择、复选框和单选,您可能会发现以下函数或任何您喜欢的内部逻辑:

addReadOnlyToFormElements = function (idElement) {
    
        // html readonly don't work on input of type checkbox and radio, neither on select. So, a safe trick is to disable the non-selected items
        $('#' + idElement + ' select>option:not([selected])').prop('disabled',true);
    
        // and, on the selected ones, to mimic readOnly appearance
        $('#' + idElement + ' select').css('background-color','#eee');
    }

没有什么比删除这些只读的更容易的了

removeReadOnlyFromFormElements = function (idElement) {

    // Remove the disabled attribut on non-selected 
    $('#' + idElement + ' select>option:not([selected])').prop('disabled',false);

    // Remove readOnly appearance on selected ones
    $('#' + idElement + ' select').css('background-color','');
}

这可能在某种程度上与其他解决方案相似,但被简化为更少的行。

假设会有一个禁用目标选项的jquery函数......

$("select[id='country']").val('PH').attr("disabled", true);
$("select[id='country']").parent().append("<input type='hidden' id='country' value='PH'>");

如果您想重新启用该选项...

$("select[id='country']").attr("disabled", false);
$("input[id='country']").remove();

此 javascript 找到所有具有“只读”属性的“选择”,然后将禁用放在“选项”中,除了选定的(用于回发)

 document.querySelectorAll("select[readonly] > option:not([selected])").forEach( (el) => el.setAttribute("disabled", "disabled") );
 without readonly: <select> <option>1</option> <option selected>2</option> <option>3</option> </select> <br> with readonly: <select readonly="readonly"> <option>1</option> <option selected>2</option> <option>3</option> </select>

下面为我​​工作:

$('select[name=country]').attr("disabled", "disabled"); 

我通过隐藏选择框并在其位置显示一个仅具有信息价值的span来管理它。 在禁用.readonly类的情况下,我们还需要删除.toVanish元素并显示.toShow元素。

 $( '.readonly' ).live( 'focus', function(e) {
                $( this ).attr( 'readonly', 'readonly' )
                if( $( this ).get(0).tagName == 'SELECT' ) {
                    $( this ).before( '<span class="toVanish readonly" style="border:1px solid; padding:5px">' 
                            + $( this ).find( 'option:selected' ).html() + '</span>' )
                    $( this ).addClass( 'toShow' )
                    $( this ).hide()
            }
    });

在一个选项中,您可以使用disabled="disabled" ,而不是选择本身

有同样的问题,发现表单submitdisabledcontrols非常有用的属性。

将其设置为 True 并且禁用的输入现在是POST

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM