Comment puis-je créer un formulaire HTML entier en «lecture seule»?

155

J'ai deux pages avec des formulaires HTML. La première page a un formulaire de soumission et la deuxième page a un formulaire de reconnaissance. Le premier formulaire offre un choix de nombreux contrôles, tandis que la deuxième page affiche à nouveau les données du formulaire de soumission avec un message de confirmation. Sur ce second formulaire, tous les champs doivent être statiques.

D'après ce que je peux voir, certains contrôles de formulaire peuvent être readonlyet tous peuvent l'être disabled, la différence étant que vous pouvez toujours accéder à un champ en lecture seule.

Plutôt que de faire ce champ par champ, existe-t-il un moyen de marquer le formulaire entier comme en lecture seule / désactivé / statique de sorte que l'utilisateur ne puisse modifier aucun des contrôles?

Mawg dit de réintégrer Monica
la source

Réponses:

310

Enveloppez les champs d'entrée et autres éléments dans un <fieldset>et donnez-lui l' disabled="disabled"attribut.

Exemple ( 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
la source
2
solution simple et géniale pour moi. Merci
démo
2
Meilleure solution côté client :) +1
Sisir
1
Assez simple, c'est la meilleure solution côté client à ce jour.
brunocoelho
Remarque: Cela a pour effet secondaire de faire "les contrôles de formulaire qui sont [les ensembles de champs] descendants, à l'exception des descendants de son premier élément <legend> facultatif ... [ne] reçoivent aucun événement de navigation, comme les clics de souris ou ceux liés au focus "( developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset ). Ainsi, tous les écouteurs d'événement js que vous avez définis sur les descendants peuvent ne pas fonctionner.
Eric Freese
2
@EricFreese Uniquement à l'état désactivé, ce que vous voulez dans 99% des cas.
Honza Kalfus
11

Tous les éléments de formulaire ne peuvent pas être définis sur readonly, par exemple:

  • cases à cocher
  • boîtes radio
  • téléchargement de fichiers
  • ...plus..

Ensuite, la solution raisonnable serait de définir tous les disabledattributs des éléments de formulaire sur true, puisque l'OP n'a pas déclaré que le formulaire "verrouillé" spécifique devrait être envoyé au serveur (ce que l' disabledattribut ne permet pas).

Une autre solution, présentée dans la démo ci-dessous, consiste à placer un calque au-dessus de l' formélément, ce qui empêchera toute interaction avec tous les éléments à l'intérieur de l' formélément, car ce calque est défini avec une z-indexvaleur plus élevée:

DÉMO:

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
la source
1
Veuillez noter que la solution CSS est incomplète car elle n'empêche pas la navigation au clavier.
Tanriol
7

Vous pouvez utiliser cette fonction pour désactiver le formulaire:

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

Voir la démo de travail ici

Notez qu'il utilise jQuery.

Sarfraz
la source
+1 Merci, mais je ne peux pas utiliser de solutions côté client, voir la question mise à jour (désolé, mon mauvais)
Mawg dit de réintégrer Monica
6

Sur la page de confirmation, ne placez pas le contenu dans des contrôles modifiables, écrivez-les simplement sur la page.

Doobi
la source
1
C'est vraiment l'approche la plus saine. Ne présentez pas un formulaire non modifiable à un utilisateur, ou vous finirez par être une entrée dans la question "Moindre étonnement".
kibibu
1
Comment? Comment puis-je afficher une case à cocher et sa condition cochée / non cochée, ou un groupe radio avec son élément sélectionné, etc.?
Mawg dit de réintégrer Monica
1
@Mawg peut-être que ce serait une option de simplement lister les éléments «sélectionnés», sans cases à cocher. Comme sur une confirmation de commande de pizza: listez simplement tous les ingrédients que vous avez sélectionnés.
marc82ch
Dans ce cas non, mais merci pour une bonne réflexion latérale qui pourrait aider les autres.
Mawg dit de réintégrer Monica le
4

Il n'y a aucun moyen intégré que je connaisse pour le faire, vous devrez donc proposer une solution personnalisée en fonction de la complexité de votre formulaire. Vous devriez lire cet article:

Convertir les formulaires HTML en lecture seule ( Mise à jour : lien de publication cassé, lien archivé )

EDIT: Sur la base de votre mise à jour, pourquoi êtes-vous si inquiet de l'avoir en lecture seule? Vous pouvez le faire via le côté client, mais sinon, vous devrez ajouter la balise requise à chaque contrôle ou convertir les données et les afficher sous forme de texte brut sans contrôle. Si vous essayez de le rendre en lecture seule pour que le prochain message ne soit pas modifié, vous avez un problème car n'importe qui peut jouer avec le message pour produire ce qu'il veut, alors lorsque vous recevez enfin les données, vous feriez mieux de le vérifier. à nouveau pour vous assurer qu'il est valide.

Kelsey
la source
+1 Merci, mais je ne peux pas utiliser de solutions côté client, voir la question mise à jour (désolé, mon mal)
Mawg dit de réintégrer Monica
"Sur la base de votre mise à jour, pourquoi êtes-vous si inquiet de l'avoir en lecture seule? Vous pouvez le faire via le côté client" Désolé, mais 1) je ne peux pas le faire côté client (pas mon choix) et 2) si cela semble à l'utilisateur comme s'il changeait des choses qui pourraient le dérouter.
Mawg dit de réintégrer Monica
@mawg bien si c'est purement pour les visuels, la seule chose que je peux recommander est de remplacer tous les contrôles en ligne par leur équivalent texte ou d'ajouter la propriété readonly aux contrôles. Il n'y a pas de solution miracle et j'ai l'impression que c'est ce que vous recherchez. Pouvez-vous publier un extrait du code que vous êtes autorisé à modifier? Il serait utile de simplement obtenir une base sur laquelle vous travaillez.
Kelsey
+1 merci pour la suggestion. Je n'avais jamais vraiment remarqué auparavant, mais j'ai dû remplir des centaines ou des milliers de formulaires et me souvenir vaguement d'une version en lecture seule, pas seulement du texte. Peut-être que je devrais en
ajouter
3
Surprise ... 6 ans plus tard, le lien ne fonctionne plus.
mwallisch le
3

Il n'y a pas de méthode HTML officielle et entièrement conforme pour le faire, mais un peu de javascript peut aller très loin. Un autre problème que vous rencontrerez est que les champs désactivés n'apparaissent pas dans les données POST

Michael Clerx
la source
4
Si vous avez déjà validé les données, vous devez quand même les enregistrer côté serveur. L'envoyer dans les deux sens au client est une grande faille de sécurité. Même si vous utilisez css, js ou html pour geler les champs, vous pouvez éditer 'm avec firebug ou en changeant manuellement la prochaine requête HTTP
Michael Clerx
+1 Merci, mais je ne peux pas utiliser de solutions côté client, voir la question mise à jour (désolé, mon mal)
Mawg dit de réintégrer Monica
3

C'est une solution idéale pour désactiver toutes les entrées , zones de texte , sélections et boutons dans un élément spécifié.

Pour jQuery 1.6 et supérieur :

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

Ou

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

jQuery 1.5 et inférieur :

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

Et

$('#myForm :input').prop('readonly', 'readonly');
Mystique
la source
2

Un autre moyen simple pris en charge par tous les navigateurs serait:

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

Mais sachez que la tabulation fonctionne toujours avec cette approche et que les éléments avec le focus peuvent toujours être manipulés par l'utilisateur.

M. Neuweiler
la source
1

Faites numéroter tous les identifiants de formulaire et exécutez une boucle for dans JS.

 for(id = 0; id<NUM_ELEMENTS; id++)
   document.getElementById(id).disabled = false; 
TTT
la source
+1 Merci, mais je ne peux pas utiliser de solutions côté client, voir la question mise à jour (désolé, mon mal)
Mawg dit de réintégrer Monica
1

Je préfère utiliser jQuery:

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

find () irait beaucoup plus loin jusqu'au nième enfant imbriqué que children (), qui ne recherche que les enfants immédiats.

user163861
la source
1
Merci, je vais vous voter pour essayer, puisque vous êtes nouveau. MAIS, veuillez noter que j'ai clairement demandé une solution uniquement côté serveur. A cette époque, je codais uniquement PHP et pas encore JS. Un conseil amical pour lire la question car certains pourraient en fait vous rejeter pour cela :-( Bienvenue à bord :-)
Mawg dit réintégrer Monica le
1

Le moyen le plus simple

$('#yourform *').prop('readonly', true);
Samir Rahimy
la source
c'est vrai, mais c'est juste un exemple d'axe, vous pouvez changer votre deuxième sélecteur en n'importe quel autre par exemple $ ('# yourform .yourclass_for_inputs'). prop ('readonly', true);
Samir Rahimy
1

Vous ajoutez une couche invisible html sur le formulaire. Par exemple

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

et style:

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

Bien sûr, l'utilisateur peut masquer cette couche dans le navigateur Web.

Marcin Żurek
la source