ฉันจะทำให้ฟอร์ม HTML ทั้งหมด“ อ่านได้อย่างเดียว” ได้อย่างไร


155

ฉันมีสองหน้าพร้อมกับฟอร์ม HTML หน้าแรกมีแบบฟอร์มการส่งและหน้าสองมีแบบฟอร์มตอบรับ แบบฟอร์มแรกเสนอทางเลือกของตัวควบคุมหลายตัวในขณะที่หน้าที่สองแสดงข้อมูลจากแบบฟอร์มการส่งอีกครั้งพร้อมข้อความยืนยัน ในรูปแบบที่สองนี้ทุกสาขาจะต้องคงที่

จากสิ่งที่ฉันเห็นการควบคุมแบบฟอร์มบางอย่างอาจเป็นไปได้readonlyทั้งหมดdisabledความแตกต่างที่คุณยังคงสามารถแท็บไปยังฟิลด์แบบอ่านอย่างเดียวได้

แทนที่จะทำฟิลด์นี้ตามฟิลด์จะมีวิธีการทำเครื่องหมายทั้งแบบเป็นแบบอ่านอย่างเดียว / ปิดการใช้งาน / คงที่ซึ่งผู้ใช้ไม่สามารถเปลี่ยนแปลงการควบคุมใด ๆ ?

คำตอบ:


309

ล้อมฟิลด์อินพุตและสิ่งอื่น ๆ ไว้ใน a <fieldset>และกำหนดdisabled="disabled"แอ็ตทริบิวต์

ตัวอย่าง ( 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>


2
วิธีการแก้ปัญหาง่ายและ greate สำหรับฉัน ขอขอบคุณ
สาธิต

2
ทางออกที่ดีที่สุดสำหรับฝั่งไคลเอ็นต์ :) +1
Sisir

1
ค่อนข้างง่ายนี่คือทางออกที่ดีที่สุดสำหรับลูกค้าจนถึงตอนนี้
brunocoelho

หมายเหตุ: สิ่งนี้มีผลข้างเคียงของการทำ "ตัวควบคุมฟอร์มที่เป็นลูกหลาน [fieldets] ยกเว้นลูกหลานขององค์ประกอบ <legend> ที่เป็นทางเลือกแรก ... [ไม่] ได้รับกิจกรรมการสืบค้นใด ๆ เช่นการคลิกเมาส์หรือวัตถุที่เกี่ยวข้องกับการโฟกัส "( developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset ) ดังนั้นผู้ฟังเหตุการณ์ js ใด ๆ ที่คุณอาจกำหนดไว้ในลูกหลานอาจไม่ทำงาน
Eric Freese

2
@EricFreese เฉพาะในสถานะปิดใช้งานซึ่งเป็นสิ่งที่คุณต้องการใน 99% ของกรณี
Honza Kalfus

11

ไม่สามารถตั้งค่าองค์ประกอบของฟอร์มทั้งหมดได้readonlyเช่น:

  • ช่องทำเครื่องหมาย
  • กล่องวิทยุ
  • อัปโหลดไฟล์
  • ...มากกว่า..

จากนั้นโซลูชันที่สมเหตุสมผลจะตั้งค่าdisabledคุณลักษณะขององค์ประกอบแบบฟอร์มทั้งหมดเป็นtrueเนื่องจาก OP ไม่ได้ระบุว่าควรส่งแบบฟอร์ม "ล็อค" เฉพาะไปยังเซิร์ฟเวอร์ (ซึ่งdisabledแอตทริบิวต์นั้นไม่อนุญาต)

วิธีแก้ปัญหาอื่นซึ่งนำเสนอในการสาธิตด้านล่างคือการวางเลเยอร์ไว้ด้านบนของformองค์ประกอบซึ่งจะป้องกันการมีปฏิสัมพันธ์กับองค์ประกอบทั้งหมดภายในformองค์ประกอบเนื่องจากเลเยอร์นั้นถูกตั้งค่าด้วยz-indexค่าที่มากขึ้น:

การสาธิต:

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>


1
โปรดทราบว่าโซลูชัน CSS ไม่สมบูรณ์เนื่องจากไม่ได้ป้องกันการนำทางด้วยแป้นพิมพ์
Tanriol

7

คุณสามารถใช้ฟังก์ชั่นนี้เพื่อปิดการใช้งานแบบฟอร์ม:

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

ดูตัวอย่างการทำงานที่นี่

โปรดทราบว่ามันใช้ jQuery


+1 ขอบคุณ แต่ฉันไม่สามารถใช้การแก้ปัญหาฝั่งไคลเอ็นต์ได้ดูคำถามที่อัปเดต (ขออภัยฉันไม่ดี)
Mawg พูดว่าการคืนสถานะโมนิก้า

6

ในหน้าการยืนยันอย่าวางเนื้อหาในส่วนควบคุมที่แก้ไขได้เพียงแค่เขียนลงในหน้า


1
นี่เป็นวิธีการที่สงบ อย่าแสดงแบบฟอร์มที่ไม่สามารถแก้ไขได้ให้กับผู้ใช้ไม่เช่นนั้นคุณจะกลายเป็นผู้เข้าร่วมในคำถาม "ความน่าเชื่อถือน้อยที่สุด"
kibibu

1
อย่างไร ฉันจะแสดงช่องทำเครื่องหมายและเงื่อนไขการตรวจสอบ / ไม่ได้ตรวจสอบหรือกลุ่มวิทยุที่มีรายการที่เลือก ฯลฯ ได้อย่างไร?
Mawg กล่าวว่าคืนสถานะโมนิก้า

1
@Mawg อาจเป็นตัวเลือกที่จะแสดงรายการ 'ที่เลือก' โดยไม่มีช่องทำเครื่องหมาย กดไลค์เพื่อยืนยันการสั่งพิซซ่า: เพียงแค่แสดงส่วนผสมทั้งหมดที่คุณเลือก
marc82ch

ในกรณีนี้ไม่ได้ แต่ขอขอบคุณสำหรับการคิดนอกกรอบที่ดีซึ่งอาจช่วยเหลือผู้อื่น
Mawg พูดว่าคืนสถานะโมนิก้า

4

ไม่มีวิธีในตัวที่ฉันรู้ว่าจะทำเช่นนี้ดังนั้นคุณจะต้องคิดหาวิธีแก้ปัญหาที่กำหนดเองขึ้นอยู่กับความซับซ้อนของรูปแบบของคุณ คุณควรอ่านโพสต์นี้:

แปลงแบบฟอร์ม HTML เป็นแบบอ่านอย่างเดียว ( อัปเดต : ลิงก์โพสต์ที่เสียหาย, ลิงก์ที่เก็บถาวร )

แก้ไข:ขึ้นอยู่กับการอัปเดตของคุณทำไมคุณกังวลเกี่ยวกับการอ่านอย่างเดียว? คุณสามารถทำมันผ่านทางฝั่งไคลเอ็นต์ แต่ถ้าไม่คุณจะต้องเพิ่มแท็กที่จำเป็นในแต่ละการควบคุมหรือแปลงข้อมูลและแสดงเป็นข้อความดิบโดยไม่มีการควบคุม หากคุณพยายามทำให้เป็นแบบอ่านอย่างเดียวเพื่อที่ว่าโพสต์ถัดไปจะไม่มีการแก้ไขคุณก็มีปัญหาเพราะใคร ๆ ก็สามารถยุ่งกับโพสต์เพื่อสร้างสิ่งที่พวกเขาต้องการดังนั้นเมื่อคุณได้รับข้อมูลที่ดีกว่า อีกครั้งเพื่อให้แน่ใจว่าถูกต้อง


+1 ขอบคุณ แต่ฉันไม่สามารถใช้การแก้ปัญหาฝั่งไคลเอ็นต์ได้ดูคำถามที่อัปเดต (ขออภัยฉันไม่ดี)
Mawg พูดว่าการคืนสถานะโมนิก้า

"จากการอัปเดตของคุณทำไมคุณถึงเป็นห่วงเรื่องการอ่านอย่างเดียวคุณสามารถทำได้ผ่านทางฝั่งลูกค้า" ขออภัย แต่ 1) ฉันไม่สามารถทำฝั่งไคลเอ็นต์ (ไม่ใช่ตัวเลือกของฉัน) และ 2) ถ้ามันดู ถึงผู้ใช้เช่นเขากำลังเปลี่ยนแปลงสิ่งต่าง ๆ ที่อาจทำให้เขาสับสน
Mawg กล่าวว่าคืนสถานะโมนิก้า

@awg ดีถ้ามันเป็นภาพล้วนๆสิ่งเดียวที่ฉันสามารถแนะนำคือแทนที่การควบคุมทั้งหมดในบรรทัดด้วยข้อความเทียบเท่าหรือเพิ่มคุณสมบัติแบบอ่านอย่างเดียวไปยังตัวควบคุม ไม่มีกระสุนเงินและฉันรู้สึกว่านั่นคือสิ่งที่คุณกำลังมองหา คุณสามารถโพสต์ตัวอย่างของรหัสที่คุณได้รับอนุญาตให้แก้ไขหรือไม่ มันจะช่วยให้ได้รับพื้นฐานสำหรับสิ่งที่คุณทำงานด้วย
Kelsey

+1 ขอบคุณสำหรับคำแนะนำ ฉันไม่เคยสังเกตเห็นมาก่อน แต่ฉันต้องกรอก 100 หรือ 1,000 ถ้าแบบฟอร์ม & จำได้อย่างชัดเจนว่าเป็นแบบอ่านอย่างเดียวไม่ใช่แค่ข้อความ บางทีฉันควรกรอกข้อมูลเพิ่มเติมและสังเกต :-)
Mawg พูดว่าการคืนสถานะโมนิก้า

3
เซอร์ไพรส์ ... 6 ปีต่อมาลิงค์ไม่ทำงานอีกต่อไป
mwallisch

3

ไม่มีวิธี HTML อย่างเป็นทางการที่จะทำ แต่ JavaScript ขนาดเล็กสามารถไปได้ไกล ปัญหาอีกประการหนึ่งที่คุณจะพบคือเขตข้อมูลที่ถูกปิดใช้งานจะไม่แสดงในข้อมูล POST


4
หากคุณตรวจสอบความถูกต้องของข้อมูลแล้วคุณต้องบันทึกฝั่งเซิร์ฟเวอร์ การส่งไปมาให้ลูกค้าเป็นช่องโหว่ความปลอดภัยขนาดใหญ่ แม้ว่าคุณจะใช้ css, js หรือ html เพื่อหยุดการทำงานของเขตข้อมูลคุณสามารถแก้ไข 'm ด้วย firebug หรือเปลี่ยนคำขอ HTTP ถัดไปด้วยตนเอง
Michael Clerx

+1 ขอบคุณ แต่ฉันไม่สามารถใช้การแก้ปัญหาด้านลูกค้าดูคำถามที่อัปเดตได้ (ขออภัยฉันไม่ดี)
Mawg พูดว่าการคืนสถานะโมนิก้า

3

นี่คือทางออกที่ดีสำหรับการปิดใช้งานทุกปัจจัยการผลิต , textareas , เลือกและปุ่มในองค์ประกอบที่ระบุ

สำหรับ jQuery 1.6 และสูงกว่า :

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

หรือ

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

jQuery 1.5 และต่ำกว่า :

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

และ

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

2

อีกวิธีง่ายๆที่เบราว์เซอร์ทุกตัวรองรับคือ:

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

แต่พึงระวังว่าการแท็บยังคงใช้ได้กับวิธีการนี้และองค์ประกอบที่มีการโฟกัสยังคงสามารถจัดการได้โดยผู้ใช้


1

มีหมายเลข id ของแบบฟอร์มทั้งหมดและเรียกใช้ for for loop ใน JS

 for(id = 0; id<NUM_ELEMENTS; id++)
   document.getElementById(id).disabled = false; 

+1 ขอบคุณ แต่ฉันไม่สามารถใช้การแก้ปัญหาด้านลูกค้าดูคำถามที่อัปเดตได้ (ขออภัยฉันไม่ดี)
Mawg พูดว่าการคืนสถานะโมนิก้า

1

ฉันควรใช้ jQuery:

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

find () จะลึกกว่าจนถึงเด็กที่อยู่ติดกันมากกว่าเด็ก () ซึ่งมองหาเด็กที่ใกล้ชิดเท่านั้น


1
ขอบคุณฉันจะโหวตให้คุณเพราะคุณเป็นคนใหม่ แต่โปรดทราบว่าฉันขอวิธีแก้ปัญหาเฉพาะฝั่งเซิร์ฟเวอร์อย่างชัดเจน ในตอนนั้นฉันเขียนโค้ด PHP เท่านั้นและยังไม่ใช่ JS คำแนะนำที่เป็นมิตรในการอ่านคำถามเนื่องจากบางคนอาจลงคะแนนให้คุณสำหรับเรื่องนี้ :-( ยินดีต้อนรับบนเรือ :-)
Mawg พูดว่าการคืนสถานะโมนิก้า

1

วิธีที่ง่ายที่สุด

$('#yourform *').prop('readonly', true);

มันเป็นความจริง แต่นี่เป็นเพียงตัวอย่างขวานคุณสามารถเปลี่ยนตัวเลือกที่สองของคุณเป็นแบบอื่นได้ตัวอย่างเช่น $ ('# yourform .yourclass_for_inputs') ของคุณ prop ('อ่านอย่างเดียว', จริง);
Samir Rahimy

1

คุณเพิ่ม html ที่มองไม่เห็นเลเยอร์เหนือแบบฟอร์ม ตัวอย่างเช่น

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

และสไตล์:

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

ผู้ใช้ Ofcourse สามารถซ่อนเลเยอร์นี้ในเว็บเบราว์เซอร์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.