How to enact DRY to refrain from repeating code. NO concat please

76 Views Asked by At

I have 2 blocks of 'for' code which are very similar with the exception for Object.values(feelings) and Object.values(feelings2) part. I am trying to create a new 'const allFeelings' that holds the following code so as to enact DRY(Don't Repeat Yourself):

tbody += '<tr>';
  tbody += `<td class="menuItem">${menuItem}</td>`;
  tbody += `<div class="hide description">${description}</div>`;
  tbody += `<td>${value}</td>`;
  tbody += '</tr>';

Please do NOT mistake this for concat as I have NO wish to concat these arrays. They are to remain separate.

    let tbody = '<tbody>';

for (const { menuItem, description, value } of Object.values(feelings)) {
    tbody += '<tr>';
    tbody += `<td class="menuItem">${menuItem}</td>`;
    tbody += `<div class="hide description">${description}</div>`;
    tbody += `<td>${value}</td>`;
    tbody += '</tr>';
}
for (const { menuItem, description, value } of Object.values(feelings2)) {
    tbody += '<tr>';
    tbody += `<td class="menuItem">${menuItem}</td>`;
    tbody += `<div class="hide description">${description}</div>`;
    tbody += `<td>${value}</td>`;
    tbody += '</tr>';
}

tbody += '</tbody>';
document.getElementById('tableData').innerHTML = tbody;
2

There are 2 best solutions below

0
On BEST ANSWER

Create a function. For example,

let tbody = '<tbody>';

function addToTableBody(feeling) {
  let returnVal = "";
  for (const {
      menuItem,
      description,
      value
    } of Object.values(feeling)) {
    returnVal += `
      <tr>
        <td class="menuItem">${menuItem}</td>
        <div class="hide description">${description}</div>
        <td>${value}</td>
      </tr>
    `
  }
  return returnVal;
}

tbody += addToTableBody(feelings)
tbody += addToTableBody(feelings2);

tbody += '</tbody>';
document.getElementById('tableData').innerHTML = tbody;
1
On

concat doesn't mutate the existing array - it creates a new array. Creating such a combined array just for the purposes of rendering and not using it afterwards would seem to work. Your feelings and feelings2 will remain separate.

Embedding everything inside a template literal will work well too.

const tbody = `
    <tbody>
        ${Object.values(feelings).concat(Object.values(feelings2)).map(({ menuItem, description, value }) => `
            <tr>
                <td class="menuItem">${menuItem}</td>
                <div class="hide description">${description}</div>
                <td>${value}</td>
            </tr>
        `)}
    </tbody>
`;