如何使用 jquery 构建动态表单构建器

Posted

技术标签:

【中文标题】如何使用 jquery 构建动态表单构建器【英文标题】:how to build dynamic form builder with jquery 【发布时间】:2017-04-11 04:18:06 【问题描述】:

我想用 jquery 开发一个动态表单构建器,用户可以在其中构建自己的表单并更改表单名称、输入类型、大小等。我知道有一些很酷的拖放在线表单构建器,但我想开发一个非常简单的表单生成器。

我已经开始开发这个,但我正面临一些问题。

当用户单击标签(输入字段)时,它会使用带有编辑和删除按钮的 jquery 动态创建一个输入字段。

下面的代码是在一个空的 div 中附加输入字段。

$(document).ready(function() 
  $(".text").click(function()
    $("#textInput").append('<input class="form-control"  type="text">' + '<input class="btn btn-default" type="button" value="Edit" id="editbtn"><input class="btn btn-default"  type="button" value="Delete" >'             ).show().css('display', 'block'));
);


    
.items 
  border: 1px solid lightgray; 
  display: none;  
  padding: 0 10px 10px 10px;
  
<div class="items" id="textInput">
  <h3>Your Form</h3>
  <hr>    
</div>

单击文本输入时,我想显示一个表格或模式,用户可以在其中保存对输入字段的更改首先编辑按钮不起作用,其次如何编辑和保存对输入字段的更改(该过程将如何工作)。

这就是我想要实现的

【问题讨论】:

【参考方案1】:

我一直致力于动态表单构建器,并从一些优秀的开源解决方案中借鉴了一些想法。

他们这样做:

    在后端将表单结构描述为 JSON。 然后使用以下库之一在前端呈现 JSON 格式。

jsonform/jsonform

源代码:jsonform/jsonform

示例:

rjsf-team/react-jsonschema-form

源代码:https://github.com/rjsf-team/react-jsonschema-form

【讨论】:

【参考方案2】:

我建议您查看从模式到表单的库(例如这里How to Create a form from a json-schema? 中描述的一些库)。

使用此类库有多种好处,其中一些是灵活的布局功能以及验证挂钩。

更重要的是,您的编辑器只能使用 JSON 结构,并且从中呈现表单并不是您最头疼的问题。

【讨论】:

【参考方案3】:

我使用 JQuery、html 和 Bootstrap 完成了这项工作

表单被构建为尽可能动态,并且还为我修改了构建

有一个脚本可以通过ajax提交表单

function d(object) 
  const id = $(object).data('check');
  $('#' + id).remove();

//picks and submits form inputs
$(document).ready(function() 
  $('form.myForm').on('submit', function() 

    var that = $(this),
      url = that.attr('action'),
      type = that.attr('method'),
      data = ;

    that.find('[name]').each(function(index, value) 
      var that = $(this),
        name = that.attr('name'),
        value = that.val();

      data[name] = value;
    );

    $.ajax(
      url: url,
      type: type,
      data: data,

      success: function(response) 

      
    );
    return false;
  );
);

$(function() 
  //here i will populate the appendi field if the user selects file
  //the user should select the file type
  $('#type').on('change', function() 
    let type = $("#type option:selected").val();
    var add;
    if (type === 'file') 
      //here i will append the new option in the appendi part
      add = "<label for=\"\">What type of file?</label>";
      add += "<select name=\"image_type\" id=\"\" class=\"form-control\">";
      add += "<option value=\"all\">All</option>";
      add += "<option value=\"image\">Image</option>";
      add += "<option value=\"document\">Document</option>";
      add += "</select>";

      $('#appendi').html(add);
    
    if (type === 'radio' || type === 'checkbox') 
      //here i will append the new option in the appendi part
      add = "<label for=\"\">Enter the names of the option separated by a comma (,)</label>";
      add += "<textarea col=\"\" class=\"form-control\" row=\"\" name=\"options\" required></textarea>";

      $('#appendi').html(add);
    
    if (type === 'paragraph' || type === 'text') 
      $('#appendi').empty();
    
  )
)

$(document).ready(function() 
  $('form.myInput').on('submit', function() 

    var that = $(this),
      data = ;

    that.find('[name]').each(function(index, value) 
      var that = $(this),
        name = that.attr('name'),
        value = that.val();

      data[name] = value;
    );
    addBody(data);
    return false;
  );
);

function addBody(data) 
  //first thing first is to generate an outer shell
  let id_tag = "shell_" + generateId(8);
  let shell1_open = "<div class='form-group' " + "id = '" + id_tag + "'>";
  shell1_open += "<button type='button' onclick='d(this)' id=\"delete\" data-check='" + id_tag + "'><i class=\"fa-minus-square\">remove</i></button>"
  let shell1_close = "</div>";
  let shell2, label, shell2_close;
  if (data.type === 'text' || data.type === 'date' || data.type === 'file' || data.type === 'email') 
    shell2 = "<input type='";
    shell2 += data.type + "'";
    shell2_close = ">";
  

  if (data.type === 'paragraph') 
    shell2 = "<textarea";
    shell2_close = "></textarea>";
  

  if (data.type === 'radio') 
    let myArr = data.options.split(",");
    shell2 = '';
    let name = 'input_' + generateId(5) + '_' + data.name.replace(/\s+/g, '');
    for (let i = 0; i < myArr.length; i++) 
      shell2 += "<input type='radio'";
      shell2 += "value ='" + myArr[i] + "'";
      shell2 += "name ='" + name + "'";
      //add a class to it
      shell2 += " class = 'form-control'";
      if (data.required === 'yes') 
        shell2 += " required";
      
      shell2 += ">" + myArr[i];
    
    shell2_close = "";
  

  if (data.type === 'checkbox') 
    let myArr = data.options.split(",");
    shell2 = '';
    for (let i = 0; i < myArr.length; i++) 
      shell2 += "<input type='checkbox'";
      shell2 += "value ='" + myArr[i] + "'";
      shell2 += " name='" + 'input_' + generateId(5) + '_' + data.name.replace(/\s+/g, '') + "'";
      //add a class to it
      shell2 += " class = 'form-control'";
      if (data.required === 'yes') 
        shell2 += " required";
      
      shell2 += ">" + myArr[i];
    
    shell2_close = "";
  

  if (data.image_type) 
    if (data.image_type === 'all') 
      shell2 += " accept";
    

    if (data.image_type === 'image') 
      shell2 += " accept='.jpeg, .png'";
    

    if (data.image_type === 'document') 
      shell2 += " accept='.pdf, .xls, .docx'";
    
  

  if (data.type !== 'radio' && data.type !== 'checkbox') 
    if (data.required === 'yes') 
      shell2 += " required";
    

    /**
     * after thinking i decided to map the name the user chose to the placeholder/label
     * and squash the name to get the input name, so to remove whitespaces
     * also i'll append input_ to all input names
     */
    shell2 += " name='" + 'input_' + generateId(5) + '_' + data.name.replace(/\s+/g, '') + "'";

    //add a class to it
    shell2 += " class = 'form-control'";

    //add placeholder
    shell2 += " placeholder = '" + data.name + '\'';
  

  $('#main-form-body').append(shell1_open + shell2 + shell2_close + shell1_close)
  //console.log(shell1_open + shell2 + shell2_close +shell1_close);


function dec2hex(dec) 
  return dec.toString(16).padStart(2, "0")


// generateId :: Integer -> String
function generateId(len) 
  var arr = new Uint8Array((len || 40) / 2)
  window.crypto.getRandomValues(arr)
  return Array.from(arr, dec2hex).join('')
<html>

<head>
  <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
  <script src="//ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
  <script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
</head>

<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">
    Add input
</button>

<form action="" method="post" class="myForm">
  <div id="main-form-body">

  </div>
  <button type='submit'>Submit</button>
</form>

<!-- The Modal -->
<div class="modal" id="myModal">
  <div class="modal-dialog">
    <div class="modal-content">

      <!-- Modal Header -->
      <div class="modal-header">
        <h4 class="modal-title">Add form input</h4>
        <button type="button" class="close" data-dismiss="modal">&times;</button>
      </div>

      <form action="" method="get" class="myInput">
        <!-- Modal body -->
        <div class="modal-body">
          <div class="form-group">
            <label for="">What should this be called?</label>
            <input type="text" name="name" class="form-control">
          </div>

          <div class="form-group">
            <label for="">What type of data will it hold?</label>
            <select name="type" id="type" class="form-control">
              <option value="text">Text</option>
              <option value="paragraph">Paragraph</option>
              <option value="file">File</option>
              <option value="radio">Radio</option>
              <option value="checkbox">Checkbox</option>
              <option value="date">Date</option>
            </select>
          </div>

          <div class="form-group" id="appendi">

          </div>

          <div class="form-group">
            <label>Should it be a required field?</label>
            <select name="required" id="" class="form-control">
              <option value="yes">yes</option>
              <option value="no">no</option>
            </select>
          </div>

        </div>

        <!-- Modal footer -->
        <div class="modal-footer">
          <button type="submit" class="btn btn-primary">Add</button>
          <button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
        </div>
      </form>

    </div>
  </div>
</div>

</html>

【讨论】:

以上是关于如何使用 jquery 构建动态表单构建器的主要内容,如果未能解决你的问题,请参考以下文章

动态表单构建器——建造者模式

如何在 Wix 中使用 JavaScript 代码构建动态搜索表单?

如何使用 JQuery 和 Rails 创建类似 Wufoo(表单构建器)的 Web 应用程序?

从搜索表单动态构建 WHERE 子句时如何防止 SQL 注入?

如何将动态表单保存到数据库/编辑表单回来

如何在 MongoDb 中存储动态生成的表单的结果?