it-swarm.com.ru

HTML форма только для чтения SELECT tag/input

Согласно спецификациям HTML, тег select в HTML не имеет атрибута readonly, только атрибут disabled. Поэтому, если вы хотите, чтобы пользователь не мог изменить выпадающий список, вы должны использовать disabled.

Единственная проблема заключается в том, что отключенные вводы HTML-форм не включаются в данные POST/GET.

Как лучше всего эмулировать атрибут readonly для тега select и при этом получать данные POST?

482
Jrgns

Вы должны сохранить элемент selectdisabled, но также добавить еще один скрытый 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>

405
bezmax

Мы могли бы также использовать это 

Отключить все, кроме выбранной опции:

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

Таким образом, раскрывающийся список все еще работает (и отправляет свое значение), но пользователь не может выбрать другое значение.

Демо

142
vimal1083

Вы можете повторно включить выбранный объект при отправке.

EDIT: т.е. обычно отключаем тег 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);
});
98
kemiller2002

другой способ сделать атрибут readOnly для элемента select - использовать css

вы могли бы сделать как:

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

DEMO

46
Yaje
<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 для Windows и Google Chrome.

38
Grant Wagner

Простое решение jQuery

Используйте это, если ваш выбор имеет класс readonly

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

Или это, если ваш выбор имеет атрибут readonly="readonly"

$('select[readonly="readonly"] option:not(:selected)').attr('disabled',true);
31
Black Brick Software

Простое решение CSS:

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

select[readonly] option{
    display:none;
}

Это приводит к тому, что Select становится серым с красивым курсором «отключить» при наведении курсора
и при выборе списка опций «пусто», поэтому вы не можете изменить его значение.

19
d.raev

Еще один более современный вариант (без каламбура) - отключить все параметры элемента select, кроме выбранного. 

заметьте, однако, что это особенность HTML 4.0 .__ и 6,7,8 бета 1, кажется, не уважают это.

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

12
epeleg

Это лучшее решение, которое я нашел:

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

Приведенный выше код отключает все остальные параметры, не выбранные при сохранении выбранного параметра включенным. При этом выбранная опция войдет в данные обратной передачи.

9
Leniel Maccaferri

Еще проще: Добавить атрибут style к вашему тегу select :

style="pointer-events: none;"
7
mainak chakraborty

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

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

Стиль скрывает все параметры и группы, когда выбор находится в состоянии readonly, поэтому пользователь не может изменить свой выбор.

Нет необходимости в взломах JavaScript.

6
nrofis

Установите флажок «отключить», если вы планируете сделать его доступным только для чтения, а затем удалите атрибут «отключен» непосредственно перед отправкой формы.

// 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
5
Craig Ambrose

Это самое простое и лучшее решение .. Вы установите readolny attr на свой выбор или любой другой attr, такой как data-readonly, и выполните следующее

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

В дополнение к отключению опций, которые не должны быть выбраны, я хотел, чтобы они фактически исчезли из списка, но все еще были в состоянии включить их, если мне потребуется позже:

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

Он находит все элементы выбора с атрибутом «только для чтения», затем находит все параметры внутри тех элементов выбора, которые не были выбраны, затем скрывает их и отключает их.

Важно разделить запрос jquery на 2 по соображениям производительности, потому что jquery читает их справа налево, код: 

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

сначала найдет все невыбранные параметры в документе, а затем отфильтрует те, которые находятся внутри выделенных элементов, с атрибутом только для чтения.

5
cernunnos

Если вы отключите поле формы, оно не будет отправлено при отправке формы. Итак, если вам нужна readonly, которая работает как disabled, но отправка значений делает это:

После любого изменения только для чтения свойств элемента.

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

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

Один простой подход на стороне сервера - удалить все опции, кроме той, которую вы хотите выбрать. Таким образом, в 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);
4
David

Решение с 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();
});
3
jBelanger

Если вы используете jquery validate, вы можете сделать следующее ниже, я использовал атрибут disabled без проблем:

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

То, что я нашел, прекрасно работает с простым javascript (то есть: библиотека JQuery не требуется), это изменение innerHTML тега <select> на желаемое единственное оставшееся значение.

До:

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

Таким образом, визуальный эффект не изменится, и это будет POST/GET в <FORM>.

2
Syd

Вслед за предложением Гранта Вагнера; Вот фрагмент кода jQuery, который делает это с помощью функций-обработчиков вместо прямых атрибутов onXXX:

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

};
2
thetoolman

Я решил это с помощью jquery:

      $("select.myselect").bind("focus", function(){
        if($(this).hasClass('readonly'))
        {
          $(this).blur();   
          return;
        }
      });
2
ownking
<select id="case_reason" name="case_reason" disabled="disabled">

disabled="disabled" -> получит ваше значение из базы данных и покажет его в виде .readonly="readonly" ->Вы можете изменить свое значение в selectbox, но ваше значение не может быть сохранено в вашей базе данных.

1
Afwan Zikri

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

Правка: добавлены методы удаления

1
Kadmillos

Вместо самого выбора вы можете отключить все параметры, кроме выбранного в данный момент. Это дает вид рабочего раскрывающегося списка, но только вариант, который вы хотите передать, является допустимым выбором.

1
Adam Bellaire

Просто удалите атрибут disabled перед отправкой формы.

    $('form').submit(function () {
        $("#Id_Unidade").attr("disabled", false);
    });
1
Wendell Carvalho

Ниже работало для меня:

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

Я знаю, что это не поможет всем (если вы только на стороне клиента), но поможет тем, у кого полный стек и контроль как за бэкендом, так и за фронтом.

Если у пользователя нет прав на редактирование поля, я возвращаю только текущий выбор для выпадающего списка.

Вот некоторые из моих внутренних контроллеров:

        #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
0
Sam

очень просто. Первое значение магазина в переменной. Затем при изменении события установите значение сохраненной переменной, которая содержит начальное значение 

У меня есть чье имя отображается. Тогда мой код будет следующим;

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

В IE я смог победить подход onfocus => onblur, дважды щелкнув мышью . Но запоминание значения и его восстановление в событии onchange, похоже, решило эту проблему.

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

Вы можете сделать подобное без свойств расширения, используя переменную javascript.

0
Sojourneer

Я справился с этим, скрыв поле выбора и показав вместо него 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()
            }
    });
0
fiatjaf
 var selectedOpt; // инициализировать var 
 var newIdForHidden; // инициализировать var 
 $ ('. disabledOnEdit'). focusin (function () {
 selectedOpt = $ (this) .find (": selected"). val (); 
 newIdForHidden = $ (this) .attr ('id) ') +' Скрытый '; 
 //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) ; 
}); 
0
Robin

Если у вас есть тег выбора, который должен быть доступен только для чтения, вы должны логически преобразовать поле выбора в одно текстовое поле.

Я говорю логически, потому что это похоже на: "Я должен показать значение пользователю"

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

Таким образом, по логике вы используете тег выбора только при первой вставке значения.

Затем, когда вам нужно отобразить это значение, вы должны поместить его в «текстовое поле только для чтения».

То же самое для множественного выбора, который становится списком значений (выбранное значение), если только для чтения

Я использую «текст», потому что тэгу только для чтения не нужен атрибут «тип» . Cheers

0
Mindexperiment

Если с момента рождения выпадающий список доступен только для чтения и не требует изменений, возможно, вам следует использовать другой элемент управления? Как простой <div> (плюс скрытое поле формы) или <input type="text">?

Добавлено: Если раскрывающийся список не всегда доступен только для чтения и JavaScript используется для его включения/отключения, то это все же решение - просто измените DOM на лету.

0
Vilx-

Вот попытка использовать пользовательскую функцию 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);

});
0
tamersalama

select multiply почти не отвечает на приведенные выше предложения по коду. С БОЛЬШИМ кувалдой и клудгингом я закончил с этим:

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);
    });
});
0
gordon