JSON в HTML: создавать шаблоны в зависимости от значения поля JSON (только ES6)

Я пытаюсь перебрать вложенный объект JSON, используя .map(), и вывести разные шаблоны HTML в зависимости от JSON inputType: "value". Я хочу использовать правильный шаблон (литерал шаблона es6) на основе Тернарного оператора и добавить правильный HTML в DOM.

Я продвинулся довольно далеко, но у меня возникла проблема с Уровнем 6 (шаблон формы) и Уровнем 7 (шаблоны ввода). Может кто-то указать мне верное направление?

Codepen: https://codepen.io/oneezy/pen/GxENOr

введите здесь описание изображения

JS (полный javascript был опущен.. см. codepen)

/* FORM (Level 6)
⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼ */
function formTEMPLATE(form) {
  return `
  ${form.map(function(form) {
    return `
      ${form.inputType['text'] ? textfieldTEMPLATE(form.inputType) : ''}
      ${form.inputType['select'] ? selectTEMPLATE(form.inputType) : ''}
      ${form.inputType['radio'] ? radioTEMPLATE(form.inputType) : ''}
      ${form.inputType['checkbox'] ? checkboxTEMPLATE(form.inputType) : ''}
    `}).join('')}`
}


/* ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ INPUT TEMPLATES ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ */


/* TEXTFIELDS (Level 7)
⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼ */
function textfieldTEMPLATE(text) {
  return `
    ${text.map(function(text) {
     return `
        <label>${text.labelText}</label>
        <input type="${text.inputType}" id="${text.inputId} name="${text.inputClass}">
    `}).join('')}`
}

/* SELECT MENU (Level 7)
⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼ */
function selectTEMPLATE(select) {
  return `
  <select class="select">
      ${select.map(function(select) {
       return `
          <option id="${select.inputID} name="${select.inputGROUP}" ${select.inputOPTION}">${select.inputLABEL}</option>
      `}).join('')}
  </select>`
}

/* RADIO (Level 7)
⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼ */
function radioTEMPLATE(radio) {
  return `
  <ul class="radio">
      ${radio.map(function(radio) {
       return `
        <li>
          <input type="${radio.inputTYPE}" id="${radio.inputID}" name="${radio.inputGROUP}" ${radio.inputOPTION}>
          <label for="${radio.inputID}">${radio.inputLABEL}</label>
        </li>
      `}).join('')}
  </ul>` 
}

/* CHECKBOX (Level 7)
⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼ */
function checkboxTEMPLATE(checkbox) {
  return `
  <ul class="checkbox">
      ${checkbox.map(function(checkbox) {
       return `
        <li>
          <input type="${checkbox.inputTYPE}" id="${checkbox.inputID}" name="${checkbox.inputGROUP}" ${checkbox.inputOPTION}>
          <label for="${checkbox.inputID}">${checkbox.inputLABEL}</label>
        </li>
      `}).join('')}
  </ul>`
}

JSON (полный json был опущен.. см. codepen)

[
  {
    "appLabel": "App",
    "appFolders": [
      {
        "folderLabel": "Folder",
        "folderFiles": [
          {
            "fileLabel": "File",
            "fileSections": [
              {
                "sectionLabel": "Select Menu",
                "sectionGroups": [
                  {
                    "groupLabel": "Group",
                    "groupInputs": [
                      {
                        "labelText": "Select 1",
                        "inputType": "select",
                        "inputId": "select1",
                        "inputClass": "select-1",
                        "inputCollection": [
                          {
                            "collectionLabelText": "Option 1",
                            "collectionInputType": "select",
                            "collectionInputId": "option1",
                            "collectionInputClass": "option-1",
                            "collectionInputName": "select-name-1"
                          },

person Oneezy    schedule 28.03.2018    source источник
comment
с какой проблемой вы столкнулись?   -  person Sphinx    schedule 28.03.2018
comment
Извините, я не понимаю вашего вопроса?   -  person Oneezy    schedule 28.03.2018
comment
Мои входные данные формы не отображаются   -  person Oneezy    schedule 28.03.2018


Ответы (1)


form.inputType['text'] ? textfieldTEMPLATE(form.inputType) : ''

проблема здесь в том, что form.inputType имеет строковое значение .. text | select и т. д. ... но этот код проверяет, есть ли у form.inputType свойство с именем text ... это не так...

Итак, возможно, вы хотите form.inputType == 'text' ? textfieldTEMPLATE(form.inputType) : ''

Тем не менее, это только одна проблема решена... другая - это то, что вы делаете внутри textfieldTEMPLATE и т. д.... выполняя .map для переданной строки... строки не имеют метода сопоставления

Итак, вы хотите изменить следующее: обратите внимание, функции *TEMPLATE вызываются с параметром form, а не form.inputType, потому что form — это object с полезными свойствами для создания элементов, тогда как form.inputType — это строка, которая не помогает для того, что вы хотите сделать

function formTEMPLATE(form) {
    return `${form.map(function(form) {
        return `
            ${form.inputType == 'text' ? textfieldTEMPLATE(form) : ''}
            ${form.inputType == 'select' ? selectTEMPLATE(form) : ''}
            ${form.inputType == 'radio' ? radioTEMPLATE(form) : ''}
            ${form.inputType == 'checkbox' ? checkboxTEMPLATE(form) : ''}
        `}
    ).join('')}`;
}

function textfieldTEMPLATE(text) {
    return `
        <label>${text.labelText}</label>
        <input type="${text.inputType}" id="${text.inputId} name="${text.inputClass}">
        <br />
    `;
}

function selectOptionTEMPLATE(options) {
    return options.inputCollection.map(function(option) {
        return `<option id="${option.collectionInputId} name="${option.collectionInputName}" ${option.collectionInputOption || ''}">${option.collectionLabelText}</option>`
    }).join('');
}

function selectTEMPLATE(select) {
    return `<select class="select">${selectOptionTEMPLATE(select)}</select>`;
}

function cbRadioTEMPLATE(x) {
    return x.inputCollection.map(function(input) {
        return `<li>
            <input type="${x.inputType}" id="${input.collectionInputId}" name="${input.collectionInputName}" ${input.collectionInputOption || ''}>
            <label for="${input.collectionInputId}">${input.collectionLabelText}</label>
        </li>`;
    }).join('');
}

function radioTEMPLATE(radio) {
    return `<ul class="radio">${cbRadioTEMPLATE(radio)}</ul>`;
}

function checkboxTEMPLATE(checkbox) {
    return `<ul class="checkbox">${cbRadioTEMPLATE(checkbox)}</ul>`;;
}

Обратите внимание на функцию function cbRadioTEMPLATE(x) — потому что и флажок, и переключатель используют этот код для «списка» полей — код DRY FTW: p

Посмотрите, как это работает, на странице https://codepen.io/anon/pen/xWpqRw.

используя функции стрелок, приведенный выше код можно упростить до

const formTEMPLATE = form => form.map(item => `
  ${item.inputType == "text" ? textfieldTEMPLATE(item) : ""}
  ${item.inputType == "select" ? selectTEMPLATE(item) : ""}
  ${item.inputType == "radio" ? radioTEMPLATE(item) : ""}
  ${item.inputType == "checkbox" ? checkboxTEMPLATE(item) : ""}
`).join("");

const textfieldTEMPLATE = text => `<label>${text.labelText}</label><input type="${text.inputType}" id="${text.inputId} name="${text.inputClass}"><br/>`;

const selectOptionTEMPLATE = options => options.inputCollection.map(option => `
  <option id="${option.collectionInputId} name="${option.collectionInputName}" ${option.collectionInputOption || ""}">${option.collectionLabelText}</option>
`).join("");

const selectTEMPLATE = select =>`<select class="select">${selectOptionTEMPLATE(select)}</select>`;

const cbRadioTEMPLATE = x => x.inputCollection.map(input => `
  <li><input type="${x.inputType}" id="${input.collectionInputId}" name="${input.collectionInputName}" ${input.collectionInputOption || ""}>
    <label for="${input.collectionInputId}">${input.collectionLabelText}</label>
  </li>
`).join("");

const radioTEMPLATE = radio => `<ul class="radio">${cbRadioTEMPLATE(radio)}</ul>`;

const checkboxTEMPLATE = checkbox =>`<ul class="checkbox">${cbRadioTEMPLATE(checkbox)}</ul>`;

И еще одна оптимизация

const typeMap = {
  text: textfieldTEMPLATE,
  select: selectTEMPLATE,
  radio: radioTEMPLATE,
  checkbox: checkboxTEMPLATE
};
const formTEMPLATE = form => form.map(item => `${typeMap[item.inputType](item)}`).join("");
person Jaromanda X    schedule 28.03.2018
comment
странно, вы говорите ES6 только в заголовке и не используете =>, чтобы сделать свой код немного более кратким - person Jaromanda X; 28.03.2018
comment
Благодаря тонну! Я копаюсь во всем сейчас, и это выглядит солидно - person Oneezy; 28.03.2018
comment
Я все еще конденсирую это - person Oneezy; 28.03.2018
comment
большое спасибо! Я всегда пытаюсь максимально упростить код... вот почему я заявил, что хочу использовать только es6. С другими оптимизациями, которые вы делаете, это действительно помогает понять все намного яснее. - person Oneezy; 28.03.2018
comment
Я заметил одну вещь, которая делала код немного трудным для чтения (из-за преттифицированного кода) такие вещи, как return ` ${form.map(function(form) {...}).join("")}`;... наличие form.map внутри строки шаблона просто делало его менее читаемым (для меня)... сравните с return form.map(function(form) {...}).join(""); - тот же результат (я думаю?!?) - person Jaromanda X; 28.03.2018
comment
Верно.. Я тоже это заметил с первой версии. Что ж, я внимательно изучу ваши оптимизации и изучу, что именно вы сделали. Потому что вы, по сути, сократили код на 100 строк, и за это я вам бесконечно благодарен :D - person Oneezy; 28.03.2018
comment
Конечно, меньше очередей — это не всегда хорошо. Он все еще должен быть читаемым. Я думаю, что это все еще так, но другие могут не согласиться. - person Jaromanda X; 28.03.2018