Search code examples
javascripthtmlinnerhtml

Dynamically replacing HTML with innerHTML not working as intended


I have a renderWorkoutUpdated function which takes in an object with updated values and the intention is to replace the particular workout record with the updated one.

_renderWorkoutUpdated(currentWorkout) {
    let html = `<li class="workout workout--${currentWorkout.type}" data-id="${
      currentWorkout.id
    }">

    <div class="container">
        <div class="workout__title">
        ${currentWorkout.description}
        </div>
      <div class="dropdown">
        <div class="kebab-menu">
            <div class="bar"></div>
            <div class="bar"></div>
            <div class="bar"></div>        
        </div>
        <div class="dropdown-content" id="dropdownContent">
        <div class="option">Edit</div>
        <div class="option">Delete</div>
        <div class="option">Delete All</div>
        </div>
      </div>
    </div>       
    
    <div class="workout__details">
      <span class="workout__icon">${
        currentWorkout.type === 'running' ? '🏃🏻' : '🚴🏻'
      }</span>
      <span class="workout__value">${currentWorkout.distance}</span>
      <span class="workout__unit">km</span>
    </div>
    <div class="workout__details">
      <span class="workout__icon">⏱</span>
      <span class="workout__value">${currentWorkout.duration}</span>
      <span class="workout__unit">min</span>
    </div>`;

    if (currentWorkout.type === 'running')
      html += `
    <div class="workout__details">
      <span class="workout__icon">⚡️</span>
      <span class="workout__value">${currentWorkout.pace.toFixed(1)}</span>
      <span class="workout__unit">min/km</span>
    </div>
    <div class="workout__details">
      <span class="workout__icon">🦶🏼</span>
      <span class="workout__value">${currentWorkout.cadence}</span>
      <span class="workout__unit">spm</span>
    </div>
  </li>`;

    if (currentWorkout.type === 'cycling')
      html += `
    <div class="workout__details">
    <span class="workout__icon">⚡️</span>
    <span class="workout__value">${currentWorkout.speed.toFixed(1)}</span>
    <span class="workout__unit">km/h</span>
  </div>
  <div class="workout__details">
    <span class="workout__icon">⛰</span>
    <span class="workout__value">${currentWorkout.elevationGain}</span>
    <span class="workout__unit">m</span>
  </div>
</li> `;

    document.querySelector(
      `.workout[data-id="${currentWorkout.id}"]`
    ).innerHTML = html;
  }

The updated form looks like this. The first record is the updated one and it should look like the 2nd and 3rd record i.e. not create another container within the container. Thanks.


Solution

  • You're putting the new <li> inside the old <li>, but I think you want to replace one with the other.

    Simply leave out the <li> tag in html, just put the new contents there. If you need to change attributes of the existing element, do that separately.

    _renderWorkoutUpdated(currentWorkout) {
      let html = `<div class="container">
            <div class="workout__title">
            ${currentWorkout.description}
            </div>
          <div class="dropdown">
            <div class="kebab-menu">
                <div class="bar"></div>
                <div class="bar"></div>
                <div class="bar"></div>        
            </div>
            <div class="dropdown-content" id="dropdownContent">
            <div class="option">Edit</div>
            <div class="option">Delete</div>
            <div class="option">Delete All</div>
            </div>
          </div>
        </div>       
        
        <div class="workout__details">
          <span class="workout__icon">${
            currentWorkout.type === 'running' ? '🏃🏻' : '🚴🏻'
          }</span>
          <span class="workout__value">${currentWorkout.distance}</span>
          <span class="workout__unit">km</span>
        </div>
        <div class="workout__details">
          <span class="workout__icon">⏱</span>
          <span class="workout__value">${currentWorkout.duration}</span>
          <span class="workout__unit">min</span>
        </div>`;
    
      if (currentWorkout.type === 'running')
        html += `
        <div class="workout__details">
          <span class="workout__icon">⚡️</span>
          <span class="workout__value">${currentWorkout.pace.toFixed(1)}</span>
          <span class="workout__unit">min/km</span>
        </div>
        <div class="workout__details">
          <span class="workout__icon">🦶🏼</span>
          <span class="workout__value">${currentWorkout.cadence}</span>
          <span class="workout__unit">spm</span>
        </div>
      </li>`;
    
      if (currentWorkout.type === 'cycling')
        html += `
        <div class="workout__details">
        <span class="workout__icon">⚡️</span>
        <span class="workout__value">${currentWorkout.speed.toFixed(1)}</span>
        <span class="workout__unit">km/h</span>
      </div>
      <div class="workout__details">
        <span class="workout__icon">⛰</span>
        <span class="workout__value">${currentWorkout.elevationGain}</span>
        <span class="workout__unit">m</span>
      </div> `;
    
      let curWorkout =
        document.querySelector(
          `.workout[data-id="${currentWorkout.id}"]`
        );
      curWorkout.innerHTML = html;
      curWorkout.className = `workout workout-${currentWorkout.type}`;
    }