Como criar um formulário HTML inteiro "somente leitura"?

155

Eu tenho duas páginas com formulários HTML. A primeira página possui um formulário de envio e a segunda página possui um formulário de confirmação. O primeiro formulário oferece uma escolha de vários controles, enquanto a segunda página exibe os dados do formulário de envio novamente com uma mensagem de confirmação. Nesse segundo formulário, todos os campos devem ser estáticos.

Pelo que pude ver, alguns controles de formulário podem ser readonlye todos podem ser disabled, a diferença é que você ainda pode tabular para um campo somente leitura.

Em vez de fazer esse campo por campo, existe alguma maneira de marcar todo o formulário como somente leitura / desativado / estático, de modo que o usuário não possa alterar nenhum dos controles?

Mawg diz que restabelece Monica
fonte

Respostas:

309

Coloque os campos de entrada e outras coisas em um <fieldset>e atribua a ele disabled="disabled".

Exemplo ( http://jsfiddle.net/7qGHN/ ):

<form>
    <fieldset disabled="disabled">
        <input type="text" name="something" placeholder="enter some text" />
        <select>
            <option value="0" disabled="disabled" selected="selected">select somethihng</option>
            <option value="1">woot</option>
            <option value="2">is</option>
            <option value="3">this</option>
        </select>
    </fieldset>
</form>

Klemen Tušar
fonte
2
solução simples e divertida para mim. Thanks
demo
2
Melhor solução para lado do cliente :) +1
Sisir
1
Muito simples, esta é a melhor solução do lado do cliente até agora.
Brunocoelho
Nota: Isso tem o efeito colateral de criar "os controles de formulário que são descendentes [dos conjuntos de campos], exceto os descendentes do seu primeiro elemento <legend> opcional ... [não] recebem eventos de navegação, como cliques do mouse ou eventos relacionados ao foco "( developer.mozilla.org/pt-BR/docs/Web/HTML/Element/fieldset ). Portanto, qualquer ouvinte de evento js que você tenha definido em descendentes pode não funcionar.
Eric Freese
2
@EricFreese Apenas no estado desativado, que é o que você deseja em 99% dos casos.
Honza Kalfus
11

Nem todos os elementos do formulário podem ser definidos como readonly, por exemplo:

  • caixas de seleção
  • caixas de rádio
  • upload de arquivo
  • ...Mais..

A solução razoável seria definir todos os disabledatributos dos elementos do formulário true, pois o OP não declarou que o formulário "bloqueado" específico deveria ser enviado ao servidor (o que o disabledatributo não permite).

Outra solução, apresentada na demonstração abaixo, é colocar uma camada em cima do formelemento que impedirá qualquer interação com todos os elementos dentro do formelemento, pois essa camada é configurada com um z-indexvalor maior :

DEMO:

var form = document.forms[0], // form element to be "readonly"
    btn1 = document.querySelectorAll('button')[0],
    btn2 = document.querySelectorAll('button')[1]

btn1.addEventListener('click', lockForm)
btn2.addEventListener('click', lockFormByCSS)

function lockForm(){
  btn1.classList.toggle('on');
  [].slice.call( form.elements ).forEach(function(item){
      item.disabled = !item.disabled;
  });
}

function lockFormByCSS(){
  btn2.classList.toggle('on');
  form.classList.toggle('lock');
}
form{ position:relative; } 
form.lock::before{
  content:'';
  position:absolute;
  z-index:999;
  top:0;
  right:0;
  bottom:0;
  left:0;
}

button.on{ color:red; }
<button type='button'>Lock / Unlock Form</button>
<button type='button'>Lock / Unlock Form (with CSS)</button>
<br><br>
<form>
  <fieldset>
    <legend>Some Form</legend>
    <input placeholder='text input'>
    <br><br>
    <input type='file'>
    <br><br>
    <textarea placeholder='textarea'></textarea>
    <br><br>
    <label><input type='checkbox'>Checkbox</label>
    <br><br>
    <label><input type='radio' name='r'>option 1</label>
    <label><input type='radio' name='r' checked>option 2</label>
    <label><input type='radio' name='r'>option 3</label>
    <br><br>
    <select>
      <option>options 1</option>
      <option>options 2</option>
      <option selected>options 3</option>
    </select>
  </fieldset>
</form>

vsync
fonte
1
Observe que a solução CSS está incompleta, pois não impede a navegação no teclado.
Tanriol 20/07
7

Você pode usar esta função para desativar o formulário:

function disableForm(formID){
  $('#' + formID).children(':input').attr('disabled', 'disabled');
}

Veja a demonstração de trabalho aqui

Observe que ele usa jQuery.

Sarfraz
fonte
1 Obrigado, mas eu não posso usar soluções do lado do lado do cliente, ver pergunta atualizada (desculpe, meu mau)
MAWG diz Reintegrar Monica
6

Na página de confirmação, não coloque o conteúdo em controles editáveis, basta escrevê-los na página.

Doobi
fonte
1
Esta é realmente a abordagem mais correta. Não apresente um formulário não editável a um usuário, ou você acabará sendo uma entrada na pergunta "Menos espanto".
Kibibu
1
como? Como posso exibir uma caixa de seleção e sua condição de verificação / não marcada, ou um grupo de rádio com o item selecionado, etc?
Mawg diz que restabelece Monica 18/08/10
1
@Mawg talvez seja uma opção apenas listar os itens 'selecionados', sem caixas de seleção. Como em uma confirmação de pedido de pizza: basta listar todos os ingredientes que você selecionou.
Marc82ch
Nesse caso, não, mas obrigado por um bom pensamento lateral que pode ajudar os outros.
Mawg diz que restabelece Monica
4

Não sei como fazer isso, então você precisará criar uma solução personalizada, dependendo da complexidade do seu formulário. Você deve ler este post:

Converter formulários HTML em somente leitura ( atualização : link de postagem quebrado, link arquivado )

EDIT: Com base na sua atualização, por que você está tão preocupado em tê-la somente leitura? Você pode fazer isso pelo lado do cliente, mas, caso contrário, precisará adicionar a tag necessária a cada controle ou converter os dados e exibi-los como texto bruto, sem controles. Se você está tentando torná-lo somente leitura para que a próxima postagem não seja modificada, você tem um problema, porque qualquer pessoa pode mexer com a postagem para produzir o que quiser, quando você realmente receber os dados, é melhor verificar isso. novamente para garantir que seja válido.

Kelsey
fonte
1 Obrigado, mas eu não posso usar soluções do lado do lado do cliente, ver pergunta atualizada (desculpe, meu mau)
MAWG diz Reintegrar Monica
"Com base na sua atualização, por que você está tão preocupado em tê-la somente leitura? Você pode fazê-lo pelo lado do cliente" Desculpe, mas 1) não posso fazê-lo do lado do cliente (não é minha escolha) e 2) se parecer para o usuário como se ele estivesse mudando coisas que podem confundi-lo.
Mawg diz que restabelece Monica 18/08/10
@mawg bem, se for apenas para efeitos visuais, a única coisa que posso recomendar é substituir todos os controles incorporados pelo seu equivalente em texto ou adicionar a propriedade readonly aos controles. Não há bala de prata e sinto que é isso que você está procurando. Você pode postar um trecho do código que você pode modificar? Seria bom apenas obter uma base para o que você está trabalhando.
Kelsey19 de
+1 obrigado pela sugestão. Eu realmente nunca notei antes, mas devo ter preenchido 100 ou 1.000 se os formulários e vagamente me lembro de uma versão apenas deles, não apenas de texto. Talvez eu deva preencher um pouco mais e observar :-)
Mawg diz para reinstalar Monica em 18/08/10
3
Surpresa ... 6 anos depois, o link não está mais funcionando.
mwallisch
3

Não existe uma maneira HTML totalmente compatível e oficial de fazer isso, mas um pouco de javascript pode percorrer um longo caminho. Outro problema que você encontrará é que os campos desabilitados não aparecem nos dados do POST

Michael Clerx
fonte
4
Se você já validou os dados, precisará salvá-los do lado do servidor. Enviá-lo de um lado para o outro é um grande problema de segurança. Mesmo se você usar css, js ou html para congelar os campos que você pode editar 'm com firebug ou mudando manualmente a próxima solicitação HTTP
Michael Clerx
+1 Obrigado, mas não posso usar soluções do lado do cliente, consulte a pergunta atualizada (desculpe, meu problema)
Mawg diz que restabelece Monica
3

Esta é uma solução ideal para desativar todas as entradas , áreas de texto , seleções e botões em um elemento especificado.

Para o jQuery 1.6 e superior :

// To fully disable elements
$('#myForm :input').prop('disabled', true); 

Ou

// To make elements readonly
$('#myForm :input').prop('readonly', true); 

jQuery 1.5 e abaixo :

$('#myForm :input').prop('disabled', 'disabled');

E

$('#myForm :input').prop('readonly', 'readonly');
Místico
fonte
2

Outra maneira simples suportada por todos os navegadores seria:

HTML:

<form class="disabled">
  <input type="text" name="name" />
  <input type="radio" name="gender" value="male">
  <input type="radio" name="gender" value="female">
  <input type="checkbox" name="vegetarian">
</form>

CSS:

.disabled {
  pointer-events: none;
  opacity: .4;
}

Mas lembre-se de que as guias ainda funcionam com essa abordagem e os elementos com foco ainda podem ser manipulados pelo usuário.

M. Neuweiler
fonte
1

Tenha todos os IDs do formulário numerados e execute um loop for em JS.

 for(id = 0; id<NUM_ELEMENTS; id++)
   document.getElementById(id).disabled = false; 
TTT
fonte
+1 Obrigado, mas não posso usar soluções do lado do cliente, consulte a pergunta atualizada (desculpe, meu problema)
Mawg diz que restabelece Monica
1

Prefiro usar o jQuery:

$('#'+formID).find(':input').attr('disabled', 'disabled');

find () seria muito mais profundo até o enésimo filho aninhado do que children (), que procura apenas filhos imediatos.

user163861
fonte
1
Obrigado, vou votar você por tentar, já que você é novo. MAS, observe que pedi claramente uma solução apenas para o servidor. Naquele momento, eu apenas codifiquei PHP e ainda não JS. Uma dica amigável para ler a pergunta, já que alguns podem até te dar um
voto negativo
1

Caminho mais fácil

$('#yourform *').prop('readonly', true);
Samir Rahimy
fonte
é verdade, mas este é apenas um exemplo de ax. Você pode alterar seu segundo seletor para outro, por exemplo $ ('# yourform .yourclass_for_inputs'). prop ('readonly', true);
Samir Rahimy
1

Você adiciona camada invisível html ao formulário. Por exemplo

<div class="coverContainer">
<form></form>
</div>

e estilo:

.coverContainer{
    width: 100%;
    height: 100%;
    z-index: 100;
    background: rgba(0,0,0,0);
    position: absolute;
}

É claro que o usuário pode ocultar essa camada no navegador da web.

Marcin Żurek
fonte