2
votes

I want to develop a dynamic form builder with jquery where users can build their own form and change form name, input type, size etc. I know there are some cool drag and drop online form builders but i want to develop a very simple form builder .

I already have started to develop this and i am facing some issues.

when user will click on the label(input field) it create an input field dynamically with jquery with edit and delete button.

The code below is appending input field in a div which is empty right now.

$(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>

On clicking the text input i want to display a table or modal where user can save changes to input field first of all the edit button is not working and secondly how to edit and save changes to input field(how the process will work).

This is what i want to achieveenter image description here

3

3 Answers

2
votes

I have been working on dynamic form builder and borrowed ideas from some excellent open-source solutions.

They do it in this way:

  1. describe form structure as JSON in the backend.
  2. then use one of the following libraries to render JSON to form in the frontend.

jsonform/jsonform

source code: jsonform/jsonform

example:

enter image description here

rjsf-team/react-jsonschema-form

source code: https://github.com/rjsf-team/react-jsonschema-form

enter image description here

0
votes

I'd suggest you to look at schema-to-form libraries (for example some of those described in here How to Create a form from a json-schema?).

There are multiple benefits of using such libraries, some of which are flexible layout capabilities, as well as validation hooks.

What is more, your editor has to work with JSON structure only and rendering a form from it is not your main headache.

0
votes

I did this using JQuery, HTML and Bootstrap

the form was built to be as dynamic as possible and built also to me modified

there is a script to submit the form via 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>