Como garantir que um campo de formulário <selecionar> seja enviado quando desativado?

180

Eu tenho um selectcampo de formulário que quero marcar como "somente leitura", pois o usuário não pode modificar o valor, mas o valor ainda é enviado com o formulário. O uso do disabledatributo evita que o usuário altere o valor, mas não envia o valor com o formulário.

O readonlyatributo está disponível apenas para inpute textareacampos, mas é basicamente isso que eu quero. Existe alguma maneira de fazer isso funcionar?

Duas possibilidades que estou considerando incluem:

  • Em vez de desabilitar o select, desative todos os se optionuse CSS para esmaecer a seleção, para que pareça desabilitada.
  • Adicione um manipulador de eventos de clique ao botão enviar para ativar todos os menus suspensos desabilitados antes de enviar o formulário.
Marquês Wang
fonte
2
desculpe por se atrasar, no entanto, as soluções fornecidas pela @ trafalmadorianworkest são as melhores. Desativa todas as entradas que não estão selecionadas. Também funcionaria se selecionar várias opções ativadas. $('#toSelect')find(':not(:selected)').prop('disabled',true);
Abhishek Madhani
Como alternativa, você pode deixar o controle desativado na interface do usuário, mas recuperar o valor no método de ação: public ActionResult InsertRecord (modelo MyType) {if (model.MyProperty == null) {model.MyProperty = Request ["MyProperty"]; }}
beastieboy 24/11

Respostas:

118
<select disabled="disabled">
    ....
</select>
<input type="hidden" name="select_name" value="selected value" />

Onde select_nameestá o nome que você normalmente daria ao<select> .

Outra opção.

<select name="myselect" disabled="disabled">
    <option value="myselectedvalue" selected="selected">My Value</option>
    ....
</select>
<input type="hidden" name="myselect" value="myselectedvalue" />

Agora, com este, notei que, dependendo do servidor da web que você estiver usando, talvez seja necessário hiddeninserir a entrada antes ou depois do<select> .

Se minha memória me serve corretamente, com o IIS, você o coloca antes, com o Apache, depois. Como sempre, o teste é fundamental.

Jordan S. Jones
fonte
3
Como isso dependeria do servidor da web ? Não é o cliente que renderiza a página com o campo selecionar e, portanto, em caso de conflito como esse, seria o cliente que decide se deve enviar o valor ao servidor ou não?
Ilari Kajaste
8
Depende de como o servidor lida com várias entradas com o mesmo nome.
Jordan S. Jones
1
É melhor você não iria contar com um tipo de servidor específico, então eu acho que a primeira abordagem é mais limpo e menos propenso a erros ..
Lucas
5
@ Jordânia: Os navegadores não enviam valores de campos desabilitados para o servidor, e é por isso que eles estão vazios quando você tenta lidar com eles no lado do servidor. Se você tiver um campo oculto com o valor desejado e os campos visíveis estiverem desativados, apenas o campo oculto será enviado ao servidor. Portanto, o campo oculto só deve ser criado (via JS ou código do servidor) quando os campos visíveis estiverem desativados e não houver problema de prioridade.
Matt van Andel
1
Essa é a única opção se você precisar de um formulário que funcione sem javascript.
Andrew
224

Desative os campos e ative-os antes do envio do formulário:

Código jQuery:

jQuery(function ($) {        
  $('form').bind('submit', function () {
    $(this).find(':input').prop('disabled', false);
  });
});
Tres
fonte
15
Uma ótima solução!
Chris
2
Este é o que eu decidi, principalmente porque é o menos invasivo.
31413 Jonathan
3
Os documentos do jQuery recomendam o uso de .prop e .removeProp para 'selected', 'selected' e 'disabled' em vez de .attr e .removeAttr ver http://api.jquery.com/prop/
Jim Bergman
2
Parte relevante do comentário de @ JimBergman - "As propriedades geralmente afetam o estado dinâmico de um elemento DOM sem alterar o atributo HTML serializado. Os exemplos incluem a propriedade value dos elementos de entrada, a propriedade desativada de entradas e botões ou a propriedade marcada de uma caixa de seleção. O método .prop () deve ser usado para definir desativado e verificado, em vez do método .attr (). O método .val () deve ser usado para obter e definir o valor. " - from api.jquery.com/prop
Joshua Dance
2
Você é gênio um (Y)
TommyDo
13

Eu estive procurando uma solução para isso, e desde que eu não encontrei uma solução neste segmento, fiz o meu.

// With jQuery
$('#selectbox').focus(function(e) {
    $(this).blur();
});

Simples, você apenas desfoca o campo quando se concentra nele, algo como desativá-lo, mas na verdade envia os dados.

Jean Paul Rumeau
fonte
Uau Ótima e fácil solução. Obrigado .. +1 de mim :)
Naeem Ul Wahhab 24/02
Eu gosto muito disso ... dependendo das interações no meu formulário, os elementos ficam ativados / desativados repetidamente ... como reativar um campo "desfocado" nesse cenário?
bkwdesign
No Google, parece com $ ('# selectbox'). Off ('focus'); faria o truque de re-permitindo
bkwdesign
2
obras para caixas de texto, não funciona para caixas de seleção, além de super fácil de obter em torno clicando e segurando o botão para baixo
Andrew
7

Fui confrontado com um cenário um pouco diferente, pois queria apenas não permitir que o usuário alterasse o valor selecionado com base em uma caixa de seleção anterior. O que acabei fazendo foi desativar todas as outras opções não selecionadas na caixa de seleção usando

$('#toSelect')find(':not(:selected)').attr('disabled','disabled');
trafalmadorian
fonte
Obrigado, achei o seu o mais logicamente mais simples. No entanto, attrdeve mudar com prop, seria algo parecido com$('#toSelect')find(':not(:selected)').prop('disabled',true);
Abhishek Madhani 2/14
6

Mesma solução sugerida por Tres sem usar o jQuery

<form onsubmit="document.getElementById('mysel').disabled = false;" action="..." method="GET">

   <select id="mysel" disabled="disabled">....</select>

   <input name="submit" id="submit" type="submit" value="SEND FORM">
</form>

Isso pode ajudar alguém a entender mais, mas obviamente é menos flexível que o jQuery.

Marco Demaio
fonte
Mas, não é bom para vários seletores. Pode ser que possamos usar getElementsByTagName('select')?
Lucky
6

se não funcionar com o seletor: input para campos selecionados, use este:

    jQuery(function() {

    jQuery('form').bind('submit', function() {
        jQuery(this).find(':disabled').removeAttr('disabled');
    });

    });
chhalpha
fonte
5

Eu uso o próximo código para desativar as opções nas seleções

<select class="sel big" id="form_code" name="code" readonly="readonly">
   <option value="user_played_game" selected="true">1 Game</option>
   <option value="coins" disabled="">2 Object</option>
   <option value="event" disabled="">3 Object</option>
   <option value="level" disabled="">4 Object</option>
   <option value="game" disabled="">5 Object</option>
</select>

// Disable selection for options
$('select option:not(:selected)').each(function(){
 $(this).attr('disabled', 'disabled');
});
Aleks
fonte
4

A maneira mais fácil que encontrei foi criar uma pequena função javascript vinculada ao seu formulário:

function enablePath() {
    document.getElementById('select_name').disabled= "";
}

e você pode chamá-lo em seu formulário aqui:

<form action="act.php" method="POST" name="form_name" onSubmit="enablePath();">

Ou você pode chamá-lo na função que você usa para verificar seu formulário :)

Alex PARISOT
fonte
4

Basta adicionar uma linha antes de enviar.

$ ("# XYZ"). RemoveAttr ("desativado");

PPB
fonte
2

Ou use algum JavaScript para alterar o nome do select e defina-o como desativado. Dessa forma, a seleção ainda é enviada, mas usando um nome que você não está verificando.

Byron Whitlock
fonte
2

Criei um plug-in rápido (apenas no Jquery), que salva o valor em um campo de dados enquanto uma entrada está desativada. Isso significa apenas que enquanto o campo estiver sendo desabilitado programaticamente através do jquery usando .prop () ou .attr () ... o acesso ao valor por .val (), .serialize () ou .serializeArra () sempre retornará o valor valor mesmo se desativado :)

Plugue descarado: https://github.com/Jezternz/jq-disabled-inputs

Josh Mc
fonte
2

Com base na solução do Jordan, criei uma função que cria automaticamente uma entrada oculta com o mesmo nome e o mesmo valor da seleção que você deseja tornar inválida. O primeiro parâmetro pode ser um elemento id ou jquery; o segundo é um parâmetro opcional booleano em que "true" desativa e "false" ativa a entrada. Se omitido, o segundo parâmetro alterna a seleção entre "ativado" e "desativado".

function changeSelectUserManipulation(obj, disable){
    var $obj = ( typeof obj === 'string' )? $('#'+obj) : obj;
    disable = disable? !!disable : !$obj.is(':disabled');

    if(disable){
        $obj.prop('disabled', true)
            .after("<input type='hidden' id='select_user_manipulation_hidden_"+$obj.attr('id')+"' name='"+$obj.attr('name')+"' value='"+$obj.val()+"'>");
    }else{
        $obj.prop('disabled', false)
            .next("#select_user_manipulation_hidden_"+$obj.attr('id')).remove();
    }
}

changeSelectUserManipulation("select_id");
Doglas
fonte
o 'obj' parâmetro deve ser um objeto jQuery
Doglas
1

Encontrei uma solução viável: remova todos os elementos, exceto o selecionado. Você pode alterar o estilo para algo que pareça desativado também. Usando jQuery:

jQuery(function($) {
    $('form').submit(function(){
        $('select option:not(:selected)', this).remove();
    });
});
Alftheo
fonte
0
<select id="example">
    <option value="">please select</option>
    <option value="0" >one</option>
    <option value="1">two</option>
</select>



if (condition){
    //you can't select
    $("#example").find("option").css("display","none");
}else{
   //you can select
   $("#example").find("option").css("display","block");
}
Thxopen
fonte
-8

Outra opção é usar o atributo somente leitura.

<select readonly="readonly">
    ....
</select>

Com somente leitura, o valor ainda é enviado, o campo de entrada fica acinzentado e o usuário não pode editá-lo.

Editar:

Citado em http://www.w3.org/TR/html401/interact/forms.html#adef-readonly :

  • Os elementos somente leitura recebem foco, mas não podem ser modificados pelo usuário.
  • Os elementos somente leitura estão incluídos na navegação por guias.
  • Elementos somente leitura podem ser bem-sucedidos.

Quando diz que o elemento pode ter êxito, significa que pode ser enviado, conforme indicado aqui: http://www.w3.org/TR/html401/interact/forms.html#successful-controls

Phillip Whelan
fonte
6
O controle NÃO está acinzentado e o usuário pode editá-lo. Você não leu a seção inteira e cito: "Os seguintes elementos suportam o atributo readonly: INPUT e TEXTAREA."
Carlos Rendon
3
Eu sei que essa é uma resposta antiga, mas isso realmente funciona. Não sei o motivo de muitos votos negativos.
Ze Luis