0

I have an array returnedDocs in code below (shortened via let returnedDocs = result.application.modules.module.moduleItem;) that I got as response from API, it structure is pretty complex. Some nested objects are arrays some values are placed few levels deep in the structure.

I use filter method to get only those elements that got specific value.

          let toFilterSix = returnedDocs.filter(
            o =>
              o.repeatableGroup.repeatableGroupItem.vocabularyReference
                .vocabularyReferenceItem.formattedValue._text === "Abdomen"
          );
          this.filterArray6 = toFilterSix;

Normally it works fine but in below example one of repeatableGroupItem is an array with two elements (image).

arrayInArray

I've got an error due to fact that there is unexpected array within filtered objects:

Results.vue?82a0:202 Uncaught (in promise) TypeError: Cannot read property 'vocabularyReferenceItem' of undefined
    at eval (Results.vue?82a0:202)
    at Array.filter (<anonymous>)
    at eval (Results.vue?82a0:201)

How can I avoid the error when do filter on other, non-array elements?

Here you can examine the data model, it's console.log'ed: https://lucid-villani-539a6f.netlify.com/results

2
  • please provide an example of your data model, and if possible try to rephrase and simplify your question a bit - as it stands it's a little difficult to interpreted. Commented Sep 19, 2019 at 20:21
  • You probably want to look at Test for existence of nested JavaScript object key to test for the existence of the property you're targeting before descending to it. Commented Sep 19, 2019 at 20:24

2 Answers 2

1

If you just want to ignore the arrays, you can simply test whether repeatableGroup has a vocabularyReferences property.

let toFilterSix = returnedDocs.filter(
  o =>
  o.repeatableGroup.repeatableGroupItem.vocabularyReference &&
  o.repeatableGroup.repeatableGroupItem.vocabularyReference.vocabularyReferenceItem.formattedValue._text === "Abdomen"
);

If you want to search the array as well, you can use an if statement to search that when it's an array.

let toFilterSix = returnedDocs.filter(
  o => {
    if (Array.isArray(o.repeatableGroup.repeatableGroupItem)) {
      return o.repeatableGroup.repeatableGroupItem.some(el => el.vocabularyReference.vocabularyReferenceItem.formattedValue._text === "Abdomen");
    } else {
      return o.repeatableGroup.repeatableGroupItem.vocabularyReference.vocabularyReferenceItem.formattedValue._text === "Abdomen";
    }
  });
Sign up to request clarification or add additional context in comments.

1 Comment

Great thanks! It saves the day (I used second snippet) and I have a starting point for some of my other bottlenecks with filtering and exceptions for non existing elements returned from API.
0

If you're trying to look for "Abdomen" regardless of whether it's a single object or an array of those objects, you could use [].concat(repeatableGroupItem). This allows you to safely assume you're dealing with an array instead of handling each case individually.

From there you could use .some() to determine if "Abdomen" exists within any of the items.

// This array contains 4 objects... 
//   1: repeatableGroupItem as single object, containing "Abdomen"
//   2: repeatableGroupItem as array of objects, containing "Abdomen"
//   3: repeatableGroupItem as single object, without "Abdomen"
//   4: repeatableGroupItem as array of objects, without "Abdomen"
const returnedDocs = [{ repeatableGroup: { repeatableGroupItem: { vocabularyReference: { vocabularyReferenceItem: { formattedValue: { _text: "Abdomen" } } } } } }, { repeatableGroup: { repeatableGroupItem: [{ vocabularyReference: { vocabularyReferenceItem: { formattedValue: { _text: "Abdomen" } } } }, { vocabularyReference: { vocabularyReferenceItem: { formattedValue: { _text: "Abdomen" } } } } ] } }, { repeatableGroup: { repeatableGroupItem: { vocabularyReference: { vocabularyReferenceItem: { formattedValue: { _text: "Not Abdomen" } } } } } }, { repeatableGroup: { repeatableGroupItem: [{ vocabularyReference: { vocabularyReferenceItem: { formattedValue: { _text: "Not Abdomen" } } } }, { vocabularyReference: { vocabularyReferenceItem: { formattedValue: { _text: "Not Abdomen" } } } } ] } }];

const result = returnedDocs.filter(o => {
  const item = [].concat(o.repeatableGroup.repeatableGroupItem);
  return item.some(i => i.vocabularyReference.vocabularyReferenceItem.formattedValue._text === "Abdomen");
});

//Logs items 1 and 2
console.log(result);

2 Comments

Thank you, great case to study and use. I have more of that undefined stuff within my filters :)
No problem! I wrote this simple example to more clearly explain what the .concat() is doing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.