Formulário HTML somente leitura SELECT tag / entrada

587

De acordo com as especificações HTML, a selecttag em HTML não tem um readonlyatributo, apenas um disabledatributo. Portanto, se você deseja impedir que o usuário altere a lista suspensa, é necessário usá-lo disabled.

O único problema é que as entradas de formulário HTML desabilitadas não são incluídas nos dados POST / GET.

Qual é a melhor maneira de emular o readonlyatributo de uma selecttag e ainda obter os dados POST?

Jrgns
fonte
5
Não confie nisso para o lado do servidor. Qualquer um pode criar sua própria página HTML e torná-la RW.
Brendan Byrd
11
Mas não é uma pergunta específica do PHP.
Kaleb Brasee 03/10/2013
4
Eu sugeriria não usar um elemento select nesse caso. Existe algum motivo para você não poder apenas exibir o valor como texto sem formatação?
Big McLargeHuge 4/14
2
@ppumkin seu comentário não faz sentido. Não estou dizendo que nunca há um bom caso de uso para campos de formulário ocultos ou selecionados. O OP estava com problemas para exibir algum texto na página, e eu estava simplesmente imaginando qual seria o objetivo de usar um elemento select nesse caso.
Big McLargeHuge
2
Eu devo estar lendo a pergunta errada. Ele diz que deseja desativar a seleção para que o usuário não a altere. Talvez ele precise renderizar a página com select e usar jquery para evitar alterações. Mas quando ele envia de volta, não há dados para isso. Eu estava fazendo o mesmo. Eu preciso exibir seleções que são filtradas por outras seleções e a última lista suspensa salva no DB via ajax, para que todas as anteriores sejam bloqueadas. Quando eu renderizo a página, sim, OK - eu podia exibir etiquetas em vez de seleções. Mas isso não é o problema :)
Piotr Kula

Respostas:

461

Você deve manter o selectelemento, disabledmas também adicionar outro oculto inputcom o mesmo nome e valor.

Se você reativar seu SELECT, copie seu valor para a entrada oculta em um evento onchange e desative (ou remova) a entrada oculta.

Aqui está uma demonstração:

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

bezmax
fonte
5
Se você reativar a seleção, também deverá desativar ou remover a entrada oculta (após copiar o valor conforme descrito), é claro. Caso contrário, você vai ter o valor enviado dupla
Adam
1
@max Ah !. Ok, isso também funciona. Eu assumi desde que você disse que a entrada oculta deveria ter o "mesmo nome" que a seleção tinha um nome.
Adam
2
E se eu estiver usando uma seleção múltipla?
Anyul Rivas
2
Ter dois elementos com o mesmo nome apenas postará de volta a última entrada ativada / selecionada, e não o dobro. Além disso, apenas o selectedvalor é postado de volta, não a lista inteira. Então, você hiddensenta diante do seu selecte mantém o valor selecionado. Se a seleção for desativada para "somente leitura", a postagem posterior conterá apenas o valor da entrada oculta. Se a seleção estiver ativada, a opção selecionada visível "substituirá / substituirá" o valor oculto, e esse é o valor que será postado de volta.
Piotr Kula
29
Embora essa seja a solução óbvia, ela é uma droga, pois você precisa adicionar outro campo de entrada.
318 Donato
189

Nós também poderíamos usar isso

Desative todos, exceto a opção selecionada:

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

Dessa forma, o menu suspenso ainda funciona (e envia seu valor), mas o usuário não pode selecionar outro valor.

Demo

vimal1083
fonte
3
Bom para opções dinâmicas #
Diego Favero
11
Perfeito para uma tag SELECT de valor único! Mas não funcionará para um <select multiple>, que ainda permitirá que os usuários cancelem a seleção de algumas das opções selecionadas, alterando o valor.
22816 Mikhail Bunkin
2
Suporte do navegador para o atributo optionda tagdisabled
Jo.
4
Esta é uma otima soluçao. Vou acrescentar que você pode alcançá-lo facilmente com jQuery como este: $("#yourSelectId option:not(:selected)).attr("disabled", "disabled")
Onkel-j
105

Você pode reativar o objeto selecionado ao enviar.

EDIT : ou seja, normalmente desabilitando a tag select (com o atributo desabilitado) e, em seguida, reativando-a automaticamente antes de enviar o formulário:

Exemplo com jQuery:

  • Para desativá-lo:

    $('#yourSelect').prop('disabled', true);
  • Para reativá-lo antes do envio para que os dados GET / POST sejam incluídos:

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

Além disso, você pode reativar todas as entradas desativadas ou selecionar:

$('#yourForm').on('submit', function() {
    $('input, select').prop('disabled', false);
});
kemiller2002
fonte
4
use .prop ('desativado', verdadeiro / falso) para definir a propriedade desativada. O atributo não mudará o estado real.
Paris Char
Penso que esta solução é inteligente que a solução @bezmax . Porque se adicionássemos entradas ocultas, teríamos que considerar que apenas uma de cada entrada (mesmo nome) era ativada a qualquer momento. Caso contrário, se as duas entradas estiverem ativadas, no lado do servidor, o programa terá uma matriz de entradas que pode causar exceção (por exemplo, se não lidamos com essa situação, e esperamos uma sequência e usamos 'Request.Form [FieldName] 'command)
MiT 17/11/2015
@ Kevin, funciona> 90% dos casos. Além disso, você tem que ter jquery no seu cinto ... Eh.
sitilge
Isso é muito mais limpo, a resposta aceita. Mais fácil de desfazer a lógica se você não quiser mais o elemento desativado e sem tags de entrada extras.
Haohmaru 16/02
51

Outra maneira de fazer um readOnlyatributo para um selectelemento é usandocss

você poderia fazer como:

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

DEMO

Yaje
fonte
8
Ótima solução. Mas você ainda pode alterar o valor com o teclado.
Mario Werner
1
Sim, isso é incrível. Para alterar o valor com o teclado, você teria que TAB para o elemento e ele será selecionado. Se você tornar a cor de fundo cinza ou desabilitada, também informará visualmente o usuário de que ela está "desabilitada" quando na verdade não está desabilitada. Ninguém suporta mais o IE, então quem se importa. Você também pode colocar uma tecla pressionada para impedir o padrão, se desejar.
Piotr Kula
Muito pouco ortodoxo !! Se os selecionar deve ser bloqueada a partir da página render,... .on('mouseover', function(){ ... });
Fr0zenFyr
pointer-events: noneimpede o foco do cursor do mouse. Para também impedir o foco do teclado, você pode complementá-lo desfocando imediatamente todos os eventos de foco:$('select').css('pointer-events', 'none').on('focus', function () {$(this).blur();});
Quinn Comendant
39
<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>

Testado e funcionando no IE 6, 7 e 8b2, Firefox 2 e 3, Opera 9.62, Safari 3.2.1 para Windows e Google Chrome.

Grant Wagner
fonte
15
O problema é que o menu suspenso é renderizado como se não fosse somente leitura. O usuário irá acho que a coisa não funciona ...
Lukas Eder
8
Isso é confuso para o usuário, porque ele ainda pode selecionar uma opção, mas quando a seleciona, a lista volta ao valor selecionado anteriormente. É muito mais intuitivo desativar a lista para impedir que o usuário selecione qualquer coisa.
quer
11
Eu tive um problema semelhante e resolvi exibindo apenas a opção selecionada. Não é necessário JS, menos confusão para o usuário ... <select id="countries"> <option value="7" selected="selected">Country7</option> </select>
Potherca
1
@ppumkin @dana @LukasEder Não ... não, se você pode consertar esse UX. Por exemplo, você poderia fazer algo assim onchange = 'this.selectedIndex=this.defaultIndex; alert("You should not change this..");'em vez de apenas mudando o índice selecionado em silêncio ..
Fr0zenFyr
1
@LukasEder Se alguém desconfiar da experiência do entrevistado, poderá adicionar um pouco de CSS para realmente enfatizar que a lista suspensa não deve ser alterada. Defina o cursor como not-allowede a cor de fundo como #CCC.
Alexander Dixon
36

Solução jQuery simples

Use isso se os seus selecionados tiverem a readonlyclasse

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

Ou isso se suas seleções tiverem o readonly="readonly"atributo

$('select[readonly="readonly"] option:not(:selected)').attr('disabled',true);
Black Brick Software
fonte
7
Por favor, explique seu código um pouco. Temos que adicionar uma classe 'readonly' aos elementos selecionados? Quando é que devemos chamar esse código: somente em document.ready ou sempre que uma seleção é ativada / desativada? O seu código noscript é seguro?
Anar khalilov
$(document).ready(function(){$('select option:not(:selected)').attr('disabled',true);});funciona bem em seleção única. Nenhuma classe "somente leitura" é necessária. A seleção múltipla é problemática, pois se houver mais de uma opção já selecionada e, portanto, não desativada, e um usuário selecionar uma das opções não desativadas, as outras opções selecionadas anteriormente serão desmarcadas.
Gordon
não entendo nada disso.
Piotr Kula
Desativa as opções diferentes da selecionada para as caixas de seleção com a classe "somente leitura". Se você tem o elemento select em mãos, você pode escrever:$select.find('option').not(':selected').attr('disabled', 'disabled');
Semra
1
Eu gosto desta solução. Eu mudaria o seletor para select[readonly]para que você apenas adicione o atributo readonly ao elemento - dessa forma, você não precisa tratar as seleções de maneira diferente de qualquer outro tipo. O javascript aprimora progressivamente o efeito. Lembre-se de que esta solução (e a maioria das outras) apenas ajuda o agente do usuário a fornecer a melhor experiência do usuário - na verdade, não impõe nada (isso deve ser feito no servidor, se necessário).
jgivoni
21

Solução CSS simples:

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

select[readonly] option{
    display:none;
}

Isso resulta em Selecionar para ficar cinza com o cursor "desativar" agradável ao passar o mouse
e ao selecionar a lista de opções como "vazia", ​​para que você não possa alterar seu valor.

d.raev
fonte
1
Se você tiver uma validação de CSRF (como no symfony e em muitos outros frameworks), ela não funcionará.
ThEBiShOp
11

Esta é a melhor solução que encontrei:

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

O código acima desativa todas as outras opções não selecionadas enquanto mantém a opção selecionada ativada. Ao fazer isso, a opção selecionada entrará nos dados de postagem posterior.

Leniel Maccaferri
fonte
11

Eu sei que é tarde demais, mas isso pode ser feito com CSS simples:

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

O estilo oculta todas as opções e grupos quando a seleção está no readonlyestado, para que o usuário não possa alterar sua seleção.

Não são necessários hacks JavaScript.

nrofis
fonte
Agradável e simples. Eu gosto disso.
Jonathan Parent Lévesque
Esta é uma solução muito agradável para o problema. Obrigado!
OderWat
10

Mais fácil ainda: adicione o atributo style à sua tag de seleção :

style="pointer-events: none;"
mainak chakraborty
fonte
Seu trabalho para mim, mas os eventos do ponteiro farão o suporte a vários navegadores?
Abhijit Jagtap
3
Isso não vai funcionar. O usuário pode alterar a entrada usando o teclado.
Sandhu
6

Esta é a melhor e mais simples solução. Você definirá um atributo readolny no seu select ou qualquer outro atributo como somente leitura de dados e faça o seguinte

$("select[readonly]").live("focus mousedown mouseup click",function(e){
    e.preventDefault();
    e.stopPropagation();
});
Guilherme Ferreira
fonte
1
você deve adicionar a digitação keydown do anúncio aqui, assim como o menu suspenso ainda está disponível "pressionando a tecla" e usar as teclas de seta para alterar o valor.
Apfz
5

Defina a seleção desativada quando planejar que seja somente leitura e remova o atributo desativado antes de enviar o formulário.

// 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
Craig Ambrose
fonte
Parece uma condição de corrida esperando para acontecer.
Brendan Byrd
5

Além de desabilitar as opções que não deveriam ser selecionáveis, eu queria fazê-las desaparecer da lista, mas ainda assim poder habilitá-las caso precise:

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

Ele localiza todos os elementos selecionados com um atributo somente leitura, depois encontra todas as opções dentro daquelas que não estão selecionadas, depois os oculta e desativa.

É importante separar a consulta jquery em 2 por razões de desempenho, porque o jquery as lê da direita para a esquerda, o código:

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

primeiro encontrará todas as opções não selecionadas no documento e depois filtrará as que estão dentro das seleções com um atributo somente leitura.

cernunnos
fonte
Talvez .prop("disabled", true)em vez
sam
4

Uma abordagem simples do lado do servidor é remover todas as opções, exceto a que você deseja selecionar. Portanto, no Zend Framework 1.12, se o elemento $ for um Zend_Form_Element_Select:

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

Se você desativar um campo de formulário, ele não será enviado quando o formulário for enviado. Portanto, se você precisar de um readonlyque funcione como o disabledenvio de valores, faça o seguinte:

Após qualquer alteração nas propriedades somente leitura de um elemento.

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

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

Solução com tabindex. Funciona com entradas de texto selecionadas, mas também com texto.

Basta usar uma classe .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" />

Edit: Com o Internet Explorer, você também precisa deste JS:

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

Seguindo a sugestão de Grant Wagners; Aqui está um trecho de jQuery que faz isso com funções de manipulador em vez de atributos diretos 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);
        }
    });

};
thetoolman
fonte
2

Eu resolvi isso com jquery:

      $("select.myselect").bind("focus", function(){
        if($(this).hasClass('readonly'))
        {
          $(this).blur();   
          return;
        }
      });
propriedade
fonte
Isso funcionou muito bem, embora a animação do mouse ainda mostre uma seta suspensa que parece clicável.
Johncl
Isso não está funcionando para mim no Chrome 26: a seleção ainda está totalmente funcional.
21313 Andy
Mas ele ainda aparece na lista quando você clica duas vezes no IE. Enfim, para impedir isso?
user1995781
2

Se você estiver usando o jquery validate, poderá fazer o seguinte abaixo, usei o atributo desativado sem problemas:

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

O que eu achei que funciona muito bem, com javascript simples (ou seja: nenhuma biblioteca JQuery necessária), é alterar o innerHTML da <select>tag para o valor restante único desejado.

Antes:

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

Exemplo de Javascript:

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

Depois de:

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

Dessa forma, nenhum efeito visual muda, e isso POST / GET dentro do <FORM>.

Syd
fonte
1

Em vez da seleção em si, você pode desativar todas as opções, exceto a opção atualmente selecionada. Isso dá a aparência de um menu suspenso em funcionamento, mas apenas a opção que você deseja transmitir é uma seleção válida.

Adam Bellaire
fonte
3
Em teoria, uma ótima idéia - mas NÃO há suporte para opções desabilitadas no IE antes do IE8. tinyurl.com/yle4bto
scunliffe 14/10/09
1

solução html:

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

javascript:

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

remover:

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

edit: métodos de remoção adicionados

Kadmillos
fonte
@ButtleButkus os javascript funcionam? eu acho que pode ser um browser relacionado issue.have você tentou adicionar um tabindex ao elemento
Kadmillos
1

Simplesmente, remova o atributo desativado antes de enviar o formulário.

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

disabled="disabled" ->obterá seu valor do banco de dados e mostrará no formulário. readonly="readonly" ->você pode alterar seu valor na caixa de seleção, mas não foi possível salvar seu valor no seu banco de dados.

Afwan Zikri
fonte
errado, está salvo. Parece que a propriedade 'readonly' não é processada por todos os navegadores e, portanto, não é confiável.
precisa
0

Se o menu suspenso de seleção for somente leitura desde o nascimento e não precisar mudar, talvez você deva usar outro controle? Como um simples <div>(mais o campo de formulário oculto) ou um <input type="text">?

Adicionado: se o menu suspenso não for somente leitura o tempo todo e o JavaScript for usado para habilitá-lo / desativá-lo, isso ainda será uma solução - basta modificar o DOM on-the-fly.

Vilx-
fonte
Não é apenas leitura desde o início. Eu uso o JavaScript para alterar e atualizar. Se um menu suspenso anterior tiver um determinado valor, este se tornará somente leitura.
Jrgns
Então talvez você possa substituir esse menu suspenso por uma caixa de texto on-the-fly?
Vilx-
Sim, mas a entrada sempre oculta é mais elegante na minha opinião
Jrgns 15/12/08
0

Abaixo trabalhou para mim:

$('select[name=country]').attr("disabled", "disabled"); 
John
fonte
11
FYI: o campo do formulário desativado não será incluído em um envio.
Mz_01 9/11/11
0

Eu o consegui ocultando a caixa de seleção e mostrando um spanem seu lugar apenas com valor informativo. No caso de desativar a .readonlyclasse, precisamos também remover os .toVanishelementos e mostrar o.toShow os.

 $( '.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()
            }
    });
fiatjaf
fonte
0

No IE, fui capaz de derrotar a abordagem onfocus => onblur clicando duas vezes. Mas lembrar o valor e restaurá-lo no evento onchange parece lidar com esse problema.

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

Você pode fazer similar sem expando propriedades usando uma variável javascript.

Sojourneer
fonte
0

Aqui está uma tentativa de usar uma função jQuery personalizada para obter a funcionalidade (conforme mencionado aqui):

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

});
tamersalama
fonte