skip to Main Content

I want to make a form builder application using drag and drop. I have a main <li> tag. There are other <li> and <ul> tags in the nested structure under this tag.

As a requirement of my application I need to get this structure as JSON. I think I should use a recursive function but I failed. I am using Angular and jQuery. Can you help me?

<li id="mainList" style="list-style: none;">
  <div class="row">
    <div class="col-md-12">
      <ul class="sortable ui-sortable">
        <li data-is-component="true" data-type-text="Text Field" data-type="1" data-element-id="n8b78496-04bd">
          <div class="form-group builder-component mt-1">
            <label style="font-size:smaller" for="exampleFormControlInput1">Text Field</label>
            <input type="email" class="form-control form-control-sm" placeholder="Text Field" disabled="">
          </div>
        </li>
        <li data-is-component="true" data-type-text="Number" data-type="3" data-element-id="nbdbeecb-ff2d">
          <div class="form-group builder-component mt-1">
            <label style="font-size:smaller" for="exampleFormControlInput1">Number</label>
            <input type="email" class="form-control form-control-sm" placeholder="Number" disabled="">
          </div>
        </li>
        <li id="n9cdfd2a-95ea" data-is-component="false" data-type-text="Column 2" data-type="60" data-element-id="n9cdfd2a-95ea">
          <div class="row">
            <div class="col-md-6">
              <ul class="sortable ui-sortable">
                <li data-is-component="true" data-type-text="Choice" data-type="5" data-element-id="n4488d94-bf63">
                  <div class="form-group builder-component mt-1">
                    <label style="font-size:smaller" for="exampleFormControlInput1">Choice</label>
                    <input type="email" class="form-control form-control-sm" placeholder="Choice" disabled="">
                  </div>
                </li>
              </ul>
            </div>
            <div class="col-md-6">
              <ul class="sortable ui-sortable">
                <li data-is-component="true" data-type-text="Select Box" data-type="6" data-element-id="n1179190-213f">
                  <div class="form-group builder-component mt-1">
                    <label style="font-size:smaller" for="exampleFormControlInput1">Select Box</label>
                    <input type="email" class="form-control form-control-sm" placeholder="Select Box" disabled="">
                  </div>
                </li>
                <li data-is-component="true" data-type-text="Date / Time" data-type="7" data-element-id="n2cd4518-633e">
                  <div class="form-group builder-component mt-1">
                    <label style="font-size:smaller" for="exampleFormControlInput1">Date / Time</label>
                    <input type="email" class="form-control form-control-sm" placeholder="Date / Time" disabled="">
                  </div>
                </li>
              </ul>
            </div>
          </div>
        </li>
        <li data-is-component="true" data-type-text="Color" data-type="11" data-element-id="n6103ae8-67e4">
          <div class="form-group builder-component mt-1">
            <label style="font-size:smaller" for="exampleFormControlInput1">Color</label>
            <input type="email" class="form-control form-control-sm" placeholder="Color" disabled="">
          </div>
        </li>
      </ul>
    </div>
  </div>
</li>

The JSON output I’m trying to create:

{
  "id": "mainList",
  "childs": [{
      "id": "n8b78496-04bd",
      "childs": null
    },
    {
      "id": "nbdbeecb-ff2d",
      "childs": null
    },
    {
      "id": "n9cdfd2a-95ea",
      "childs": [
        [{
          "id": "n4488d94-bf63",
          "childs": null
        }],
        [{
          "id": "n1179190-213f",
          "childs": null
        }, {
          "id": "n2cd4518-633e",
          "childs": null
        }]
      ]
    },
    {
      "id": "n6103ae8-67e4",
      "childs": null
    }
  ]
}

Thanks for your help.

2

Answers


  1. Please provide the current version of your Angular or jQuery code

    Login or Signup to reply.
  2. You can use a recursive function that collects the li elements it finds at the next level, creates objects for them and then uses recursion to do the same for each child:

    const collectChildren = (elem) => elem.tagName == "UL" 
            ? [...elem.children]
            : Array.from(elem.children, collectChildren).flat();
    
    function collectListItems(li) {
        const children = collectChildren(li);
        return {
            id: li.dataset.elementId ?? li.id,
            children: children.length ? Array.from(children, collectListItems) : null
        };
    }
    
    const result = collectListItems(document.getElementById("mainList"));
    console.log(result);
    <ul>
        <li id="mainList" style="list-style: none;">
          <div class="row">
            <div class="col-md-12">
              <ul class="sortable ui-sortable">
                <li data-is-component="true" data-type-text="Text Field" data-type="1" data-element-id="n8b78496-04bd">
                  <div class="form-group builder-component mt-1">
                    <label style="font-size:smaller" for="exampleFormControlInput1">Text Field</label>
                    <input type="email" class="form-control form-control-sm" placeholder="Text Field" disabled="">
                  </div>
                </li>
                <li data-is-component="true" data-type-text="Number" data-type="3" data-element-id="nbdbeecb-ff2d">
                  <div class="form-group builder-component mt-1">
                    <label style="font-size:smaller" for="exampleFormControlInput1">Number</label>
                    <input type="email" class="form-control form-control-sm" placeholder="Number" disabled="">
                  </div>
                </li>
                <li id="n9cdfd2a-95ea" data-is-component="false" data-type-text="Column 2" data-type="60" data-element-id="n9cdfd2a-95ea">
                  <div class="row">
                    <div class="col-md-6">
                      <ul class="sortable ui-sortable">
                        <li data-is-component="true" data-type-text="Choice" data-type="5" data-element-id="n4488d94-bf63">
                          <div class="form-group builder-component mt-1">
                            <label style="font-size:smaller" for="exampleFormControlInput1">Choice</label>
                            <input type="email" class="form-control form-control-sm" placeholder="Choice" disabled="">
                          </div>
                        </li>
                      </ul>
                    </div>
                    <div class="col-md-6">
                      <ul class="sortable ui-sortable">
                        <li data-is-component="true" data-type-text="Select Box" data-type="6" data-element-id="n1179190-213f">
                          <div class="form-group builder-component mt-1">
                            <label style="font-size:smaller" for="exampleFormControlInput1">Select Box</label>
                            <input type="email" class="form-control form-control-sm" placeholder="Select Box" disabled="">
                          </div>
                        </li>
                        <li data-is-component="true" data-type-text="Date / Time" data-type="7" data-element-id="n2cd4518-633e">
                          <div class="form-group builder-component mt-1">
                            <label style="font-size:smaller" for="exampleFormControlInput1">Date / Time</label>
                            <input type="email" class="form-control form-control-sm" placeholder="Date / Time" disabled="">
                          </div>
                        </li>
                      </ul>
                    </div>
                  </div>
                </li>
                <li data-is-component="true" data-type-text="Color" data-type="11" data-element-id="n6103ae8-67e4">
                  <div class="form-group builder-component mt-1">
                    <label style="font-size:smaller" for="exampleFormControlInput1">Color</label>
                    <input type="email" class="form-control form-control-sm" placeholder="Color" disabled="">
                  </div>
                </li>
              </ul>
            </div>
          </div>
        </li>
    </ul>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search