How to stop error when using menu

I am iterating over an objects to output an arrays in my search results. However it seems when records don’t have a given attribute array, I get an error. Here is the sandbox:

Example - if you select ISO 9000 from the company type menu, I get the error.

I am pretty new to some of this stuff so forgive me if the question is a dumb one, but any help would be appreciated as I’ve been round the houses on it for days.

Thanks

I guess this is my lack of JS knowledge. I have solved the issue by supressing the error message then hiding the div that contains the undefined element:

      <div class="product-items" style="${item.products?.map(product => product.productType).join('')=== undefined ? 'display:none' : ''}">
           <span class="product-hits-title">Product Type(s)</span>
           <ul class="product-hits">
           ${item.products?.map(product => '<li>'+product.productType+'</li>').join('')}     
           </ul>
           </div>

I am sure there is a more efficient way of achieving this, any suggestion very welcome.

Thanks

Hi Marcus,

One thing that you could try is to do a ternary like so:

${item.products ? `<div>
  <span class="product-hits-title">Product Name(s)</span>
    <ul class="product-hits">
      ${item.products
        .map((product) => '<li>' + product.productName + '</li>')
        .join('')}     
    </ul>
</div>` : ''}

This will only display the product-items div when item.products is a truthy value (and is not undefined like you are seeing here). You could use this approach for both the Product Name(s) and the Product Type(s) as I’ve done in this fork of your sandbox:

Hi Michael

Thanks so much for the suggestion, it’s a much cleaner solution. However I still get an instance of undefined. A small sample of my data looks like this

    {
      "companyType": "Manufacturer",
      "certificateRef": "FRTD301",
      "companyName": "International Expertise for Wood Industries Ltd",
      "products": [
        { "productName": "Halspan FD120", "productType": "Fire Doors - Timber / FD120" },
        { "productName": "Halspan FD90", "productType": "Fire Doors - Timber / FD90" },
        { "productName": "Halspan Prima FD30", "productType": "Fire Doors - Timber / FD30"}
      ],
       },
     {
      "companyType": "Installer",
      "certificateRef": "AA1872",
      "companyName": "FAA Installations Ltd",
      "products": [
        { "productType": "Cavity Barriers" },
        { "productType": "Service Penetration & Linear Gap Seals" },
        { "productType": "Steel Protection - Boards" },
        { "productType": "Steel Protection - Reactive Coatings" }
      ],
    },

And in my template I am using your suggestion.

            ${item.products ? `<div>
            <span class="product-hits-title">Product Name(s)</span>
              <ul class="product-hits">
                ${item.products
                  .map((product) => '<li>' + product.productName + '</li>')
                  .join('')}     
              </ul>
          </div>` : ''}
           

          ${item.products ? `<div>
          <span class="product-hits-title">Product Type(s)</span>
            <ul class="product-hits">
              ${item.products
                .map((product) => '<li>' + product.productType + '</li>')
                .join('')}     
            </ul>
        </div>` : ''}

The result for the first record is fine, but the result for the second gives an undifined as ‘products’ exists but ‘products → productName’ doesn’t. I can’t seem to construct anything that does a ternary by checking against ‘products → productName’.

Thanks again for all your assistance.

Glad I was able to help – regarding the other issue, one way to handle this is to separate the lists into two: productTypes and productNames. This way you could check these individual arrays and see if they have any values.

However, if you are unable to modify the data, one thing you can do is instead of checking if item.products is truthy, instead, we can grab all of the values of interest from the list and check the length (to see if any are present).

For example:

${item.products.map(p => p.productName).filter(v => !!v).length ? `<div>
  <span class="product-hits-title">Product Name(s)</span>
    <ul class="product-hits">
      ${item.products
        .map((product) => '<li>' + product.productName + '</li>')
        .join('')}     
    </ul>
</div>` : ''}

Let me know how this works for you! Thanks!

Hi Michael

Thanks again for your help. Unfortunately I’m unable to modify the data as it is being generated by a third party app so I have successfully used your latest suggestion. However I have had to add a ternary to ignore the initial error as this is still being thrown when we try and iterate over productName:

So this works like a dream:

            ${item.products?.map(p => p.productName).filter(v => !!v).length ? `<div>
            <span class="product-hits-title">Product Name(s)</span>
              <ul class="product-hits">
                ${item.products
                  .map((product) => '<li>' + product.productName + '</li>')
                  .join('')}     
              </ul>
          </div>` : ''}

And is still much cleaner than my initial code which hid divs using css.

Thanks again, I really appreciate it!