Search code examples
javascripthtmlarraysobjectundefined

Replacing undefined value from an array of objects with an image


<div id="en">
  <!--Begin 2COLTBL-->
  <table role="presentation" width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#F1F2F2" style="padding: 20px 0px 10px 0px;">
    <tbody>
      <tr>
        <td width="3%" class="Hide"></td>
        <td width="45%" align="center" valign="top" id="enoffer0" bgcolor="#FFFFFF" style="padding: 20px 0px 20px 0px"></td>
        <td width="3%"></td>
        <td width="45%" align="center" valign="top" id="enoffer1" bgcolor="#FFFFFF" style="padding: 20px 0px 20px 0px"></td>
        <td width="3%" class="Hide"></td>
      </tr>
    </tbody>
  </table>
  <!--End 2COLTBL-->

  <!--Begin 2COLTBL-->
  <table role="presentation" width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#F1F2F2" style="padding: 10px 0px 10px 0px;">
    <tbody>
      <tr>
        <td width="3%" class="Hide"></td>
        <td width="45%" align="center" valign="top" id="enoffer2" bgcolor="#FFFFFF" style="padding: 20px 0px 20px 0px"></td>
        <td width="3%"></td>
        <td width="45%" align="center" valign="top" id="enoffer3" bgcolor="#FFFFFF" style="padding: 20px 0px 20px 0px"></td>
        <td width="3%" class="Hide"></td>
      </tr>
    </tbody>
  </table>
  <!--End 2COLTBL-->

  <!--Begin 2COLTBL-->
  <table role="presentation" width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#F1F2F2" style="padding: 10px 0px 10px 0px;">
    <tbody>
      <tr>
        <td width="3%" class="Hide"></td>
        <td width="45%" align="center" valign="top" id="enoffer4" bgcolor="#FFFFFF" style="padding: 20px 0px 20px 0px"></td>
        <td width="3%"></td>
        <td width="45%" align="center" valign="top" id="enoffer5" bgcolor="#FFFFFF" style="padding: 20px 0px 20px 0px"></td>
        <td width="3%" class="Hide"></td>
      </tr>
    </tbody>
  </table>
  <!--End 2COLTBL-->

  <!--Begin 2COLTBL-->
  <table role="presentation" width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#F1F2F2" style="padding: 10px 0px 10px 0px;">
    <tbody>
      <tr>
        <td width="3%" class="Hide"></td>
        <td width="45%" align="center" valign="top" id="enoffer6" bgcolor="#FFFFFF" style="padding: 20px 0px 20px 0px"></td>
        <td width="3%"></td>
        <td width="45%" align="center" valign="top" id="enoffer7" bgcolor="#FFFFFF" style="padding: 20px 0px 20px 0px"></td>
        <td width="3%" class="Hide"></td>
      </tr>
    </tbody>
  </table>
  <!--End 2COLTBL-->

  <!--Begin 2COLTBL-->
  <table role="presentation" width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#F1F2F2" style="padding: 10px 0px 10px 0px;">
    <tbody>
      <tr>
        <td width="3%" class="Hide"></td>
        <td width="45%" align="center" valign="top" id="enoffer8" bgcolor="#FFFFFF" style="padding: 10px 0px 10px 0px"></td>
        <td width="3%"></td>
        <td width="45%" align="center" valign="top" id="enoffer9" bgcolor="#FFFFFF" style="padding: 10px 0px 10px 0px"></td>
        <td width="3%" class="Hide"></td>
      </tr>
    </tbody>
  </table>
  <!--End 2COLTBL-->
</div>

<script>
  const offersData = [{
      "partner": "Partner 1",
      "code": "CODE",
      "lang": "e",
      "headline": "Headline 1",
      "desc": "Description 1",
      "enddate": "ENDDATE",
      "cta": "CTA",
      "url": "URL"
    },
    {
      "partner": "Partner 2",
      "code": "CODE",
      "lang": "e",
      "headline": "Headline 2",
      "desc": "Description 2",
      "enddate": "ENDDATE",
      "cta": "CTA",
      "url": "URL"
    },
    {
      "partner": "Partner 3",
      "code": "CODE",
      "lang": "e",
      "headline": "Headline 3",
      "desc": "Description 3",
      "enddate": "ENDDATE",
      "cta": "CTA",
      "url": "URL"
    },
    {
      "partner": "Partner 4",
      "code": "CODE",
      "lang": "e",
      "headline": "Headline 4",
      "desc": "Description 4",
      "enddate": "ENDDATE",
      "cta": "CTA",
      "url": "URL"
    },
    {
      "partner": "Partner 5",
      "code": "CODE",
      "lang": "e",
      "headline": "Headline 5",
      "desc": "Description 5",
      "enddate": "ENDDATE",
      "cta": "CTA",
      "url": "URL"
    }
  ]

  const contentContainer = function offerContent() {
    return `<!--Begin 1COLTBL--> 
      <!--Begin IMGSML-->
      <div><img role="presentation" src="${this.code}_${this.lang}.png" alt="" width="150" class="Img" style="vertical-align: bottom;" border="0"></div>
      <!--End IMGSML-->
        <br>
      <h4 style="font-size: 19px; font-family: 'Montserrat', Arial, Helvetica, sans-serif; line-height: 24px; color: #FFFFFF; margin: 0; padding: 20px 10px 20px 10px; background-color: #6ccbdd" class"SubHdline">${this.headline}</h4>
      <p style="margin: 0; font-family: 'Archivo', Arial, Helvetica, sans-serif; padding: 20px 10px 20px 10px; font-size: 14px" class="Body">${this.desc}</p>
      <!--Begin BTNPRTNRRD-->
      <table role="presentation" border="0" cellpadding="0" cellspacing="0">
        <tbody>
          <tr>
            <td align="center" valign="middle" bgcolor="#145782" style="-moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; padding: 15px 30px 15px 30px;"><div><a href="${this.url}" target="_blank" style="color: #FFFFFF; display: inline-block; font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: lighter; text-align: center; text-decoration: none; -webkit-text-size-adjust: none; white-space: nowrap;" class="Fullwidth">${this.cta}</a></div></td>
          </tr>
        </tbody>
      </table>
      <!--End BTNPRTNRRD--> 
    <!--End 1COLTBL-->`
  }

  const finalData = offersData.map(obj => ({ ...obj,
    content: contentContainer
  }))

  const frenchOffer = finalData.filter((offer) => {
    return offer.lang === "f"
  })
  const englishOffer = finalData.filter((offer) => {
    return offer.lang === "e"
  })

  function displayFrench() {
    let a = 0
    const frOffer0 = document.getElementById("froffer0")
    frOffer0.innerHTML = frenchOffer[a++] ? .content()
    const frOffer1 = document.getElementById("froffer1")
    frOffer1.innerHTML = frenchOffer[a++] ? .content()
    const frOffer2 = document.getElementById("froffer2")
    frOffer2.innerHTML = frenchOffer[a++] ? .content()
    const frOffer3 = document.getElementById("froffer3")
    frOffer3.innerHTML = frenchOffer[a++] ? .content()
    const frOffer4 = document.getElementById("froffer4")
    frOffer4.innerHTML = frenchOffer[a++] ? .content()
    const frOffer5 = document.getElementById("froffer5")
    frOffer5.innerHTML = frenchOffer[a++] ? .content()
    const frOffer6 = document.getElementById("froffer6")
    frOffer6.innerHTML = frenchOffer[a++] ? .content()
    const frOffer7 = document.getElementById("froffer7")
    frOffer7.innerHTML = frenchOffer[a++] ? .content()
    const frOffer8 = document.getElementById("froffer8")
    frOffer8.innerHTML = frenchOffer[a++] ? .content()
    const frOffer9 = document.getElementById("froffer9")
    frOffer9.innerHTML = frenchOffer[a++] ? .content()
  }

  function displayEnglish() {
    let i = 0
    const enOffer0 = document.getElementById("enoffer0")
    enOffer0.innerHTML = englishOffer[i++] ? .content()
    const enOffer1 = document.getElementById("enoffer1")
    enOffer1.innerHTML = englishOffer[i++] ? .content()
    const enOffer2 = document.getElementById("enoffer2")
    enOffer2.innerHTML = englishOffer[i++] ? .content()
    const enOffer3 = document.getElementById("enoffer3")
    enOffer3.innerHTML = englishOffer[i++] ? .content()
    const enOffer4 = document.getElementById("enoffer4")
    enOffer4.innerHTML = englishOffer[i++] ? .content()
    const enOffer5 = document.getElementById("enoffer5")
    enOffer5.innerHTML = englishOffer[i++] ? .content()
    const enOffer6 = document.getElementById("enoffer6")
    enOffer6.innerHTML = englishOffer[i++] ? .content()
    const enOffer7 = document.getElementById("enoffer7")
    enOffer7.innerHTML = englishOffer[i++] ? .content()
    const enOffer8 = document.getElementById("enoffer8")
    enOffer8.innerHTML = englishOffer[i++] ? .content()
    const enOffer9 = document.getElementById("enoffer9")
    enOffer9.innerHTML = englishOffer[i++] ? .content()
  }

  displayFrench()
  displayEnglish()
</script>

I work in email dev and produce a weekly email with different client offers in it that I would like to automate. I get an excel sheet with the offers that I then convert into json. The Email is built using a two column table for about 4-10 offers a week. Looks something like this: enter image description here

as you can see in the image where there is no offer you get left with a message that says "undefined"

I have been trying to work out a piece of code that will be able to replace any undefined object in the array with a default image. Ive attached a code snippet of what my code looks like. I have tried many things but none of them work so Im wondering if anyone here is able to crack this for me.


Solution

  • I've tried to simplify your code to make it clear.

    The most important part is this one: englishOffer[i]?.content() || 'empty'

    Basically when it's out of index, it returns undefined, a falsey value. So the operator or will fallback for the next expression. I put a string value, but you can put whatever you want.

    const offersData = [{
        "partner": "Partner 1",
        "code": "CODE",
        "lang": "e",
        "headline": "Headline 1",
        "desc": "Description 1",
        "enddate": "ENDDATE",
        "cta": "CTA",
        "url": "URL"
      },
      {
        "partner": "Partner 2",
        "code": "CODE",
        "lang": "e",
        "headline": "Headline 2",
        "desc": "Description 2",
        "enddate": "ENDDATE",
        "cta": "CTA",
        "url": "URL"
      },
      {
        "partner": "Partner 3",
        "code": "CODE",
        "lang": "e",
        "headline": "Headline 3",
        "desc": "Description 3",
        "enddate": "ENDDATE",
        "cta": "CTA",
        "url": "URL"
      },
      {
        "partner": "Partner 4",
        "code": "CODE",
        "lang": "e",
        "headline": "Headline 4",
        "desc": "Description 4",
        "enddate": "ENDDATE",
        "cta": "CTA",
        "url": "URL"
      },
      {
        "partner": "Partner 5",
        "code": "CODE",
        "lang": "e",
        "headline": "Headline 5",
        "desc": "Description 5",
        "enddate": "ENDDATE",
        "cta": "CTA",
        "url": "URL"
      }
    ]
    
    const contentContainer = function offerContent() {
      return `<!--Begin 1COLTBL--> 
        <!--Begin IMGSML-->
        <div>
          <img class="image" role="presentation"
            src="${this.code}_${this.lang}.png" alt=""
          >
        </div>
        <!--End IMGSML-->
        <br>
        <h4 class="headline">${this.headline}</h4>
        <p class="body">${this.desc}</p>
        <!--Begin BTNPRTNRRD-->
        <table class="card-internal" role="presentation">
          <tbody>
            <tr>
              <td align="center" valign="middle">
                <a href="${this.url}" target="_blank" class="link">${this.cta}</a>
              </td>
            </tr>
          </tbody>
        </table>
        <!--End BTNPRTNRRD--> 
      <!--End 1COLTBL-->`
    }
    
    const finalData = offersData.map(obj => ({ ...obj,
      content: contentContainer
    }))
    
    const frenchOffer = finalData.filter((offer) => {
      return offer.lang === "f"
    })
    const englishOffer = finalData.filter((offer) => {
      return offer.lang === "e"
    })
    
    function displayEnglish() {
      for (let i = 0; i < 10; i++) {
        const key = "enoffer" + i;
        const element = document.getElementById(key)
        element.innerHTML = englishOffer[i]?.content() || 'empty';
      }
    }
    
    displayEnglish()
    table.card {
      width: 100%;
      border: 0;
      background-color: #F1F2F2;
      padding: 20px 0px 10px 0px;
    }
    
    table.card td {
      padding: 0;
      border-spacing: 0;
    }
    
    table.card td.offer {
      background-color: #FFFFFF;
      padding: 20px 0px 20px 0px;
      width: 45%;
    }
    
    img.image {
      width: 150px;
      vertical-align: bottom;
      border: 0;
    }
    
    .headline {
     font-size: 19px;
     font-family: 'Montserrat', Arial, Helvetica, sans-serif;
     line-height: 24px;
     color: #FFFFFF;
     margin: 0;
     padding: 20px 10px 20px 10px;
     background-color: #6ccbdd;
    }
    
    .body {
      margin: 0;
      font-family: 'Archivo', Arial, Helvetica, sans-serif;
      padding: 20px 10px 20px 10px;
      font-size: 14px;
    }
    
    table.card-internal {
      border: 0;
    }
    table.card-internal td {
      border-spacing: 0;
      background-color: #145782;
      -moz-border-radius: 4px; 
      -webkit-border-radius: 4px;
      border-radius: 4px;
      padding: 15px 30px 15px 30px;
    }
    
    .link {
      color: #FFFFFF;
      display: inline-block;
      font-family: Arial, Helvetica, sans-serif;
      font-size: 16px;
      font-weight: lighter;
      text-align: center; 
      text-decoration: none; 
      -webkit-text-size-adjust: none; 
      white-space: nowrap;
    }
    <div id="en">
      <table class="card" role="presentation">
        <tbody>
          <tr>
            <td width="3%" class="Hide"></td>
            <td class="offer" align="center" valign="top" id="enoffer0"></td>
            <td width="3%"></td>
            <td class="offer" align="center" valign="top" id="enoffer1"></td>
            <td width="3%" class="Hide"></td>
          </tr>
        </tbody>
      </table>
      
      <table class="card" role="presentation">
        <tbody>
          <tr>
            <td width="3%" class="Hide"></td>
            <td class="offer" align="center" valign="top" id="enoffer2"></td>
            <td width="3%"></td>
            <td class="offer" align="center" valign="top" id="enoffer3"></td>
            <td width="3%" class="Hide"></td>
          </tr>
        </tbody>
      </table>
      
      <table role="presentation">
        <tbody>
          <tr>
            <td width="3%" class="Hide"></td>
            <td class="offer" align="center" valign="top" id="enoffer4"></td>
            <td width="3%"></td>
            <td class="offer" align="center" valign="top" id="enoffer5"></td>
            <td width="3%" class="Hide"></td>
          </tr>
        </tbody>
      </table>
      
      <table class="card" role="presentation">
        <tbody>
          <tr>
            <td width="3%" class="Hide"></td>
            <td class="offer" align="center" valign="top" id="enoffer6"></td>
            <td width="3%"></td>
            <td class="offer" align="center" valign="top" id="enoffer7"></td>
            <td width="3%" class="Hide"></td>
          </tr>
        </tbody>
      </table>
      
      <table class="card" role="presentation">
        <tbody>
          <tr>
            <td width="3%" class="Hide"></td>
            <td class="offer" align="center" valign="top" id="enoffer8"></td>
            <td width="3%"></td>
            <td class="offer" align="center" valign="top" id="enoffer9"></td>
            <td width="3%" class="Hide"></td>
          </tr>
        </tbody>
      </table>
    </div>