【问题标题】:Creating a page to dynamically allow user to create forms创建页面以动态允许用户创建表单
【发布时间】:2018-09-01 15:14:24
【问题描述】:

过去几周我们一直在为一个项目苦苦挣扎,简单的想法是为我们的学校创建一个网站,用于发送和接收表格。此时,我们正在尝试创建管理员可以动态创建表单的页面,类似于 Google 表单。现在我们的 HTML 看起来像这样:

<HTML>
<HEAD>
<TITLE>Create Form</TITLE>
<link rel="stylesheet" type="text/css" href="login.css" />
<script type="text/javascript" src="createform.js"></script>
</HEAD>
<BODY>
<form method="POST">
<div id="dynamicInput">
<label for="fieldName">Name this field</label>
<input type="text" name="fieldName">
<br><br>

<SELECT name="element">
<OPTION value="text">Textbox</OPTION>
<OPTION value="radio">Radio</OPTION>
<OPTION value= "textarea">Text Area</option>
<OPTION value = "checkbox">Check Box</option>
</SELECT>

<input type="button" value="Add an option" onClick="addAllInputs('dynamicInput', document.forms[0].element.value);">
</div>


<br><br><br>

<input type = "button" value="Add another field" onClick = "addSec();">
<br><br>
</form>
</BODY>
</HTML>

我们的 JavaScript:

var counterText = 0;

var counterRadioButton = 0;

var counterCheckBox = 0;

var counterTextArea = 0;

var counter = 0;
function addAllInputs(divName, inputType){

     var newdiv = document.createElement('div');

     switch(inputType) {

          case 'text':

               newdiv.innerHTML = "Entry " +(counterText+1)+" <input type='text' name='myInputs[]'><br>";

               counterText++;

               break;

          case 'radio':

               newdiv.innerHTML = "Entry " +(counterRadioButton+1)+" <input type='radio' name='myRadioButtons[]'>";

               counterRadioButton++;

               break;

          case 'checkbox':

               newdiv.innerHTML = "Entry "+(counterCheckBox+1)+" <input type='checkbox' name='myCheckBoxes[]'>";

               counterCheckBox++;

               break;

          case 'textarea':

           newdiv.innerHTML = "Entry "+(counterTextArea+1)+" <textarea name='myTextAreas[]'>type here...</textarea>";

               counterTextArea++;

               break;
          }

     document.getElementById(divName).appendChild(newdiv);
}
function addSec(){
    var newdiv = document.createElement('div');

    var div = document.getElementById('dynamicInput').innerHTML;
    newdiv.innerHTML = document.getElementById('dynamicInput');
    document.body.appendChild(newdiv);

}

我们已经尝试了 AddSec 函数的许多不同迭代,它的目的是复制 HTML div,它构成一个表单字段。我们已经得到它来复制 div,但是它带有我们添加到原始字段中的所有“选项”,例如复选框和文本字段,并且不能以任何方式修改它。对此的任何建议都将不胜感激,我们更喜欢纯 JavaScript 方法,但如果我们能让它工作,jQuery 就可以了。

到目前为止,我已经测试了使用 .clone 函数来克隆 dynamicInput div,并且还尝试将新的 div 添加到数组中,但程序没有任何功能。

【问题讨论】:

  • 那么想要的结果是什么?为什么重复的&lt;div&gt;不能修改?
  • 预期结果是 div 模板相同,但允许将更多条目选项添加到表单的该部分。例如,我可以让第一个字段用于名称,而只有一个用于名称的文本框。然后我想创建一个新字段,这个有四个复选框,它被称为本科级别。现在的问题是 .clone 方法将使用它拥有的任何选项复制原始字段,并且不能将新选项添加​​到新字段中。使用我现在拥有的 .innerHTML 方法,什么都没有发生。
  • 您是否在.clone 中使用了深度克隆参数?为什么要将元素分配给.innerHTML?只能为其分配文本。你的意思是newdiv.innerHTML = div;
  • 是的,这就是我的意思。通过深度克隆,我认为这意味着将其设置为 true?如果是这样,是的,我遇到了同样的问题。

标签: javascript html forms clone customization


【解决方案1】:

更新

添加了Plunk


该演示使&lt;input type='text'&gt;&lt;textarea&gt;&lt;input type='checkbox'&gt;&lt;input type='radio'&gt;&lt;select&gt; 组。它还会创建额外的&lt;fieldset&gt;。每个表单控件都有一个唯一的#id 和匹配的[name],每个单选按钮都有一个唯一的 id,但每个组都有一个共同的[name]

我没有让&lt;label&gt; 成为一个选项,我想如果你遵循这个模式,你应该能够将它作为一个简单的字符串添加进去。以下是所使用的参考:

insertAdjacentHTML()

Template Literals

Event Delegation

HTMLFormControlsCollection

var formA = document.forms[0];
var formB = document.forms[1];
var ui = formA.elements;
var base = formB.elements;

formA.addEventListener('change', selectTag);
formA.addEventListener('click', addFieldset);

function selectTag(e) {
  var rad = `s${document.querySelector('.rad:checked').value}`;
  var fst = base[rad];
  var qty;
  var ask;
  var idx = -1;
  if (e.target.id === "sel") {
    idx = parseInt(e.target.value, 10);
  }
  switch (idx) {
    case 0:
      var ID0 = Math.round(new Date().valueOf() / 3000000 + performance.now());
      var input = `<input id="t${ID0}" name="t${ID0} type="text">`;
      fst.insertAdjacentHTML('beforeend', input);
      break;
    case 1:
      var ID1 = Math.round(new Date().valueOf() / 3000000 + performance.now());
      var textArea = `<textarea id="ta${ID1}" name="ta${ID1}"></textarea>`;
      fst.insertAdjacentHTML('beforeend', textArea);
      break;
    case 2:
      var ID2 = Math.round(new Date().valueOf() / 3000000 + performance.now());
      var check = `<input id="ch${ID2}" name="ch${ID2}" type='checkbox' value=''>`;
      fst.insertAdjacentHTML('beforeend', check);
      break;
    case 3:
      var ID3 = Math.round(new Date().valueOf() / 3000000 + performance.now());
      ask = prompt('Enter the number of radio buttons needed');
      var rads = [];
      qty = parseInt(ask, 10);
      var name = ID3 + Math.floor(Math.random() * 11) + 10;
      for (let i = 0; i < qty; i++) {
        var radio = `<input id="r${ID3+i}" name="r${name}" type='checkbox' value=''>`;
        rads.push(radio);
        fst.insertAdjacentHTML('beforeend', radio);
      }
      break;
    case 4:
      var ID4 = Math.round(new Date().valueOf() / 3000000 + performance.now());
      var select = `<select id="s${ID4}" name="s${ID4}"></select>`;
      ask = prompt('Enter the number of options needed');
      qty = parseInt(ask, 10);
      fst.insertAdjacentHTML('beforeend', select);
      var sel = document.getElementById('s' + ID4);
      for (let i = 0; i < qty; i++) {
        var opt = document.createElement('option');
        sel.add(opt);
      }
      break;
    default:
      break;
  }
}


function addFieldset(e) {
  if (e.target.id === 'addSet') {
    var sets = formB.querySelectorAll('fieldset').length;
    var fs = `
    <fieldset id='s${sets}'>
      <legend>${sets}</legend>
    </fieldset>`;
    formB.insertAdjacentHTML('beforeend', fs);
    var rad = `
    <input id='r${sets}' name='rad' class='rad' type='radio' value='${sets}'>
    <label for='r${sets}'>${sets}</label>`;
    ui.addSet.insertAdjacentHTML('beforebegin', rad);
  }
}
<form id='ui'>

  <fieldset id='set'>
    <legend>Create Form</legend>
    <select id='sel'>
      <option>Pick a Field</option>
      <option value='0'>Text Box</option>
      <option value='1'>Text Area</option>
      <option value='2'>Checkbox</option>
      <option value='3'>Radio Group</option>
      <option value='4'>Select</option>
    </select>
    <input id='r0' name='rad' class='rad' type='radio' value='0' checked>
    <label for='r0'>0</label>
    <input id='r1' name='rad' class='rad' type='radio' value='1'>
    <label for='r1'>1</label>
    <input id='r2' name='rad' class='rad' type='radio' value='2'>
    <label for='r2'>2</label>
    <input id='r3' name='rad' class='rad' type='radio' value='3'>
    <label for='r3'>3</label>
    <button id='addSet' type='button'>Add Fieldset</button>
  </fieldset>

</form>

<form id='base'>
  <fieldset id='s0'>
    <legend>0</legend>
  </fieldset>
  <fieldset id='s1'>
    <legend>1</legend>
  </fieldset>
  <fieldset id='s2'>
    <legend>2</legend>
  </fieldset>
  <fieldset id='s3'>
    <legend>3</legend>
  </fieldset>

</form>

【讨论】:

  • 代码在 StackOverflow 上工作,但在将其添加到我的项目后,页面看起来应该是这样,但没有任何 javascript 工作。 jQuery 代码在 Notepad++ 中是灰色的,所以我认为这意味着我需要将 jQuery 添加到库中以供文件访问,我以为我已经完成了,但似乎没有任何改变。有没有办法在没有 jQuery 或如何正确将其添加到项目中以供使用的指南的情况下做同样的事情?
  • 这确实有助于为我们的目标奠定基础。非常感谢!
  • 没问题,编码愉快。
【解决方案2】:

var counterText = 0;

var counterRadioButton = 0;

var counterCheckBox = 0;

var counterTextArea = 0;

var counter = 0;
function addAllInputs(divName, inputType){

     var newdiv = document.createElement('div');

     switch(inputType) {

          case 'text':

               newdiv.innerHTML = "Entry " +(counterText+1)+" <input type='text' name='myInputs[]'><br>";

               counterText++;

               break;

          case 'radio':

               newdiv.innerHTML = "Entry " +(counterRadioButton+1)+" <input type='radio' name='myRadioButtons[]'>";

               counterRadioButton++;

               break;

          case 'checkbox':

               newdiv.innerHTML = "Entry "+(counterCheckBox+1)+" <input type='checkbox' name='myCheckBoxes[]'>";

               counterCheckBox++;

               break;

          case 'textarea':

           newdiv.innerHTML = "Entry "+(counterTextArea+1)+" <textarea name='myTextAreas[]'>type here...</textarea>";

               counterTextArea++;

               break;
          }

     document.getElementById(divName).appendChild(newdiv);
}
function addSec(){
    var newdiv = document.createElement('div');

    var div = document.getElementById('dynamicInput').innerHTML;
    newdiv.innerHTML = document.getElementById('dynamicInput').innerHTML;
    document.body.appendChild(newdiv);

}
<HTML>
<HEAD>
<TITLE>Create Form</TITLE>
<link rel="stylesheet" type="text/css" href="login.css" />
<script type="text/javascript" src="createform.js"></script>
</HEAD>
<BODY>
<form method="POST">
<div id="dynamicInput">
<label for="fieldName">Name this field</label>
<input type="text" name="fieldName">
<br><br>

<SELECT name="element">
<OPTION value="text">Textbox</OPTION>
<OPTION value="radio">Radio</OPTION>
<OPTION value= "textarea">Text Area</option>
<OPTION value = "checkbox">Check Box</option>
</SELECT>

<input type="button" value="Add an option" onClick="addAllInputs('dynamicInput', document.forms[0].element.value);">
</div>


<br><br><br>

<input type = "button" value="Add another field" onClick = "addSec();">
<br><br>
</form>
</BODY>
</HTML>
你错过了一个innerHTML。

【讨论】:

  • 这允许 div 被克隆,但问题仍然存在,添加到原始字段的选项也被克隆,并且尝试向新字段添加新选项只是将它们添加到原始字段.我的理论是我需要为每个创建的新 div 创建某种新的 id,并且我需要以某种方式防止原始字段的选项也被复制。
  • 那么你想要生成的表单是初始状态还是新状态?
  • 一个新的状态,或者空白,以便管理员可以分别自定义每个选项。
猜你喜欢
  • 2018-07-15
  • 1970-01-01
  • 2013-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多