Генерация JSON на основе выбранных вложенных флажков - PullRequest
0 голосов
/ 02 июля 2018

Я динамически создал группу входов для флажков на основе JSON. Теперь я хочу получить все выбранные флажки в виде массива в форме parent-children, как указано ниже:

let data = {
  "personal-information": {
    "label": "personal-information",
    "children": {
      "first_name": {
        "type": "string",
        "label": "First Name",
        "optional": false
      },
      "last_name": {
        "type": "string",
        "label": "Last Name",
        "optional": false
      },
      "dob": {
        "type": "date",
        "label": "Date Of Birth",
        "optional": false
      },
      "gender": {
        "type": "string",
        "label": "Gender",
        "optional": false
      },
      "height": {
        "type": "string",
        "label": "Height",
        "optional": false
      },
      "weight": {
        "type": "string",
        "label": "Weight",
        "optional": false
      },
      "blood-group": {
        "type": "string",
        "label": "Blood-Group",
        "optional": false
      },
      "addresses": {
        "label": "addresses",
        "children": {
          "address-line-1": {
            "type": "string",
            "label": "Address",
            "optional": false
          },
          "address-line-2": {
            "type": "string",
            "label": "Address",
            "optional": false
          },
          "city": {
            "type": "string",
            "label": "City",
            "optional": false
          },
          "state": {
            "type": "string",
            "label": "State",
            "optional": false
          },
          "country": {
            "type": "string",
            "label": "Country",
            "optional": false
          },
          "zipcode": {
            "type": "string",
            "label": "Zip Code",
            "optional": false
          }
        }
      },
      "emergency-contact": {
        "label": "emergency-contact",
        "children": {
          "name": {
            "type": "string",
            "label": "Zip Code",
            "optional": false
          },
          "phone": {
            "type": "string",
            "label": "Phone",
            "optional": false
          },
          "email": {
            "type": "string",
            "label": "Email",
            "optional": false
          }
        }
      }
    }
  },
  "general-information": {
    "label": "general-information",
    "children": {
      "allergies": {
        "type": "String",
        "label": "Allergies",
        "optional": true
      },
      "habits": {
        "type": "String",
        "label": "Habits",
        "optional": true
      }
    }
  },
  "history": {
    "label": "history",
    "children": {
      "status": {
        "type": "Boolean",
        "label": "Status",
        "optional": false
      },
      "createdAt": {
        "type": "date",
        "label": "createdAt",
        "optional": false
      },
      "problem": {
        "type": "Text",
        "label": "Chief Complaint",
        "optional": true
      },
      "diagnosis": {
        "type": "Text",
        "label": "Diagnosis",
        "optional": true
      },
      "prescription": {
        "type": "Text",
        "label": "Prescription",
        "optional": true
      },
      "lab-result": {
        "label": "lab-result",
        "children": {
          "test-name": {
            "type": "string",
            "label": "Test Name",
            "optional": false
          },
          "loinc": {
            "type": "string",
            "label": "Loinc",
            "optional": false
          },
          "normal-range": {
            "type": "string",
            "label": "Normal Range",
            "optional": false
          },
          "unit": {
            "type": "string",
            "label": "Unit",
            "optional": false
          },
          "value": {
            "type": "string",
            "label": "Value",
            "optional": false
          },
          "test-result": {
            "type": "string",
            "label": "Test Name",
            "optional": false
          },
          "createdAt": {
            "type": "date-time",
            "label": "Time",
            "optional": false
          },
          "status": {
            "type": "Boolean",
            "label": "Status",
            "optional": false
          }
        }
      },
      "medication-history": {
        "label": "medication-history",
        "children": {
          "medication-name": {
            "type": "string",
            "label": "Medication Name",
            "optional": false
          },
          "notes": {
            "type": "string",
            "label": "Notes",
            "optional": false
          },
          "status": {
            "type": "Boolean",
            "label": "Status",
            "optional": false
          },
          "qty": {
            "type": "string",
            "label": "Quantity",
            "optional": false
          },
          "time-to-take": {
            "type": "string",
            "label": "No. of time to take",
            "optional": false
          },
          "createdAt": {
            "type": "date",
            "label": "Date",
            "optional": false
          }
        }
      }
    }
  }
};
let nodeLevel = 1;

function addItem(parentUL, branch, parentName) {
  for (var key in branch) {
    // console.log('Branch', branch[key]);
    // console.log('Key: ', key);
    var item = branch[key].children;
    // console.log('Item: ', item)

    let name = '';

    if (parentName) {
      name = parentName;
    }

    $item = $('<li>', {
      id: key
    });
    $item.append($('<input>', {
      type: "checkbox",
      id: key,
      name: key,
      value: key,
      "data-parent": name
    }));
    // $item.attr('data-parent', name);
    $item.append($('<label>', {
      for: key,
      text: key
    }));
    parentUL.append($item);
    nodeLevel++;
    if (branch[key].children) {
      var $ul = $('<ul>', {
        style: 'display: none'
      }).appendTo($item);

      addItem($ul, item, branch[key].label);
    } else {
      nodeLevel = 1;
    }
  }
}

$(function() {
  addItem($('#root'), data);
  $(':checkbox').change(function() {
    $(this).closest('li').children('ul').slideToggle();
  });

  // $('label').click(function() {
  //   $(this).closest('li').find(':checkbox').trigger('click');
  // });
});



$(".save").click(function() {

  var selected = new Array();

  var checkboxes = document.querySelectorAll('input[type=checkbox]:checked')

  let arrAll = {};
  for (var i = 0; i < checkboxes.length; i++) {
    let parent = checkboxes[i].getAttribute('data-parent');

    console.log('Checkbox: ', checkboxes[i]);
    console.log('Parent: ', parent);

    // let inputName = checkboxes[i].getAttribute('name');



    // console.log(inputName);

    // if(parent) {
    // 	arrAll[parent][inputName] = {};
    // } else {

    // 	arrAll[inputName] = {};	
    // }

    /*
    if(parent){
    	selected[parent] = [];
    	selected[parent].push(checkboxes[i].value);
    } else {
    	selected.push(checkboxes[i].value);
    } */
    // selected.push(checkboxes[i].value)
  }

  // console.log('Selected checkbox:', arrAll);

});
ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

ul ul {
  margin: 0 0 0 30px;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

<ul id="root"></ul>

<button class="save">Save</button>

Так что, если я выберу 1. личная информация -> имя и фамилия 2. личная информация -> адреса -> адресная строка-1 3. общая информация -> аллергия 4. история -> статус

мой ожидаемый результат:

{
  "personal-information":{
    "child":{
      "first_name":"first_name",
      "addresses":{
        "child":{
          "address1":"address1",
          "address2":"address2"
        }
      }
    }
  },
  "general-information":{
    "child":{
      "allergies":"allergies",
      "habits":"habits"
    }
  }
}

Как я могу сделать это с помощью jQuery или Javascript?

1 Ответ

0 голосов
/ 02 июля 2018

Вы можете рекурсивно пройтись по своему data объекту снова, как вы делали, когда создавали элементы, чтобы прочитать состояние. Вместо того, чтобы начинать с массива флажков, мы начинаем с желаемой структуры.

В этом примере я использую атрибут name, чтобы сопоставить элемент пользовательского интерфейса с исходным источником данных. Было бы лучше сохранить ссылку на него когда-нибудь при его создании. Это облегчает поиск нужного элемента и не заставляет вас полагаться на запросы DOM.

Также обратите внимание, что ваш текущий HTML-код содержит дубликаты идентификаторов элементов <li> и <checkbox> ...

Короче говоря:

  • Цикл над записями data
  • Для каждого ключа найдите элемент [name=${key}]
  • Если элемент checked, добавьте его key к объекту
  • Если значение содержит объект children, recurse.
  • Если значение не содержит children, добавьте его значение
const walkCheckedTree = (opts) => Object
    .entries(opts)
    .reduce((t, [k, v]) => {
      const cb = root.querySelector(`[name=${k}]`);

      if (cb.checked) {
        if (v.children) {
          t[k] = { child: walkCheckedTree(v.children) };
        } else {
          t[k] = k;
        }
      }

      return t;
    }, {});

const tree = walkCheckedTree(data);

Пример выполнения: (нажмите сохранить в журнал)

let data = {
  "personal-information": {
    "label": "personal-information",
    "children": {
      "first_name": {
        "type": "string",
        "label": "First Name",
        "optional": false
      },
      "last_name": {
        "type": "string",
        "label": "Last Name",
        "optional": false
      },
      "dob": {
        "type": "date",
        "label": "Date Of Birth",
        "optional": false
      },
      "gender": {
        "type": "string",
        "label": "Gender",
        "optional": false
      },
      "height": {
        "type": "string",
        "label": "Height",
        "optional": false
      },
      "weight": {
        "type": "string",
        "label": "Weight",
        "optional": false
      },
      "blood-group": {
        "type": "string",
        "label": "Blood-Group",
        "optional": false
      },
      "addresses": {
        "label": "addresses",
        "children": {
          "address-line-1": {
            "type": "string",
            "label": "Address",
            "optional": false
          },
          "address-line-2": {
            "type": "string",
            "label": "Address",
            "optional": false
          },
          "city": {
            "type": "string",
            "label": "City",
            "optional": false
          },
          "state": {
            "type": "string",
            "label": "State",
            "optional": false
          },
          "country": {
            "type": "string",
            "label": "Country",
            "optional": false
          },
          "zipcode": {
            "type": "string",
            "label": "Zip Code",
            "optional": false
          }
        }
      },
      "emergency-contact": {
        "label": "emergency-contact",
        "children": {
          "name": {
            "type": "string",
            "label": "Zip Code",
            "optional": false
          },
          "phone": {
            "type": "string",
            "label": "Phone",
            "optional": false
          },
          "email": {
            "type": "string",
            "label": "Email",
            "optional": false
          }
        }
      }
    }
  },
  "general-information": {
    "label": "general-information",
    "children": {
      "allergies": {
        "type": "String",
        "label": "Allergies",
        "optional": true
      },
      "habits": {
        "type": "String",
        "label": "Habits",
        "optional": true
      }
    }
  },
  "history": {
    "label": "history",
    "children": {
      "status": {
        "type": "Boolean",
        "label": "Status",
        "optional": false
      },
      "createdAt": {
        "type": "date",
        "label": "createdAt",
        "optional": false
      },
      "problem": {
        "type": "Text",
        "label": "Chief Complaint",
        "optional": true
      },
      "diagnosis": {
        "type": "Text",
        "label": "Diagnosis",
        "optional": true
      },
      "prescription": {
        "type": "Text",
        "label": "Prescription",
        "optional": true
      },
      "lab-result": {
        "label": "lab-result",
        "children": {
          "test-name": {
            "type": "string",
            "label": "Test Name",
            "optional": false
          },
          "loinc": {
            "type": "string",
            "label": "Loinc",
            "optional": false
          },
          "normal-range": {
            "type": "string",
            "label": "Normal Range",
            "optional": false
          },
          "unit": {
            "type": "string",
            "label": "Unit",
            "optional": false
          },
          "value": {
            "type": "string",
            "label": "Value",
            "optional": false
          },
          "test-result": {
            "type": "string",
            "label": "Test Name",
            "optional": false
          },
          "createdAt": {
            "type": "date-time",
            "label": "Time",
            "optional": false
          },
          "status": {
            "type": "Boolean",
            "label": "Status",
            "optional": false
          }
        }
      },
      "medication-history": {
        "label": "medication-history",
        "children": {
          "medication-name": {
            "type": "string",
            "label": "Medication Name",
            "optional": false
          },
          "notes": {
            "type": "string",
            "label": "Notes",
            "optional": false
          },
          "status": {
            "type": "Boolean",
            "label": "Status",
            "optional": false
          },
          "qty": {
            "type": "string",
            "label": "Quantity",
            "optional": false
          },
          "time-to-take": {
            "type": "string",
            "label": "No. of time to take",
            "optional": false
          },
          "createdAt": {
            "type": "date",
            "label": "Date",
            "optional": false
          }
        }
      }
    }
  }
};
let nodeLevel = 1;

function addItem(parentUL, branch, parentName) {
  for (var key in branch) {
    // console.log('Branch', branch[key]);
    // console.log('Key: ', key);
    var item = branch[key].children;
    // console.log('Item: ', item)

    let name = '';

    if (parentName) {
      name = parentName;
    }

    $item = $('<li>', {
      id: key
    });
    $item.append($('<input>', {
      type: "checkbox",
      id: key,
      name: key,
      value: key,
      "data-parent": name
    }));
    // $item.attr('data-parent', name);
    $item.append($('<label>', {
      for: key,
      text: key
    }));
    parentUL.append($item);
    nodeLevel++;
    if (branch[key].children) {
      var $ul = $('<ul>', {
        style: 'display: none'
      }).appendTo($item);

      addItem($ul, item, branch[key].label);
    } else {
      nodeLevel = 1;
    }
  }
}

$(function() {
  addItem($('#root'), data);
  $(':checkbox').change(function() {
    $(this).closest('li').children('ul').slideToggle();
  });

  // $('label').click(function() {
  //   $(this).closest('li').find(':checkbox').trigger('click');
  // });
});



$(".save").click(function() {
  const root = document.getElementById("root");
  
  const walkCheckedTree = (opts) => Object
    .entries(opts)
    .reduce((t, [k, v]) => {
      const cb = root.querySelector(`[name=${k}]`);

      if (cb.checked) {
        if (v.children) {
          t[k] = { child: walkCheckedTree(v.children) };
        } else {
          t[k] = k;
        }
      }
      
      return t;
    }, {});
  
  const tree = walkCheckedTree(data);
  
  console.log(tree);
});
ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

ul ul {
  margin: 0 0 0 30px;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

<ul id="root"></ul>

<button class="save">Save</button>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...