0

I am trying to filter a Javascript array of objects with nested objects with specific properties. I can filter the name, slug, website, launch year without any issues. But, I can not filter the category name (category.name) which is an object within the object. Why is filtering the category name not working?

            var search = "qui"; // does not work (category.name)
            // var search = "Sauer"; // works (name)

            var data = [{ "name": "Sauer-Metz", "slug": "ab-laborum", 
              "website": "https://test.com", "launch_year": 2017,  "category_id": 6,
              "category": { "id": 6, "name": "qui", "slug": "qui" } } ];

            var results = data.filter(company => [
                'name', 'launch_year', 'website', 'category.name'
            ].some(key => String(company[key]).toLowerCase().includes(search.toLowerCase())));

            console.log(results);

4 Answers 4

1

One way you can go about it is to have a value extractor like the one getKey below

const getKey = (value, key) => {
    return key.split('.').reduce((acc, curr) => value[curr], '');
 }
 
 

 var results = data.filter(company => [
            'name', 'launch_year', 'website', 'category.name'
        ].some(key => String(getKey(company, key)).toLowerCase().includes(search.toLowerCase())));
Sign up to request clarification or add additional context in comments.

Comments

0

I believe you have to do a separate condition for this specific nested property, although there might be a cleaner way I don't see right now:

var results = data.filter(
  (company) =>
    ["name", "launch_year", "website"].some((key) =>
      String(company[key]).toLowerCase().includes(search.toLowerCase())
    ) ||
    String(company["category"]["name"])
      .toLowerCase()
      .includes(search.toLowerCase())
);

Comments

0

Dot notation doesn't work like that.

const testCase1 = 'qui';
const testCase2 = 'Sauer';

const data = [
    {
        name: 'Sauer-Metz',
        slug: 'ab-laborum',
        website: 'https://test.com',
        launch_year: 2017,
        category_id: 6,
        category: { id: 6, name: 'qui', slug: 'qui' },
    },
];

const searchResults = (data, search) => {
    return data.filter((item) => {
        return (
            item?.category?.name.toLowerCase().includes(search.toLowerCase()) ||
            ['name', 'launch_year', 'website'].some((key) => `${item[key]}`.toLowerCase().includes(search.toLowerCase()))
        );
    });
};

console.log('**CASE 1**')
console.log(searchResults(data, testCase1));
console.log('**CASE 2**')
console.log(searchResults(data, testCase2));

Comments

0

To use your approach you can convert 'category.name' to ['category','name'] and then use String(company[key[0]][key[1]])... whenever key is an array.

const search = "qui"; // does not work (category.name)
//const search = "Sauer"; // works (name)

const data = [{ "name": "Sauer-Metz", "slug": "ab-laborum",  "website": "https://test.com", "launch_year": 2017,  "category_id": 6, "category": { "id": 6, "name": "qui", "slug": "qui" } } ];

const results = data.filter(
    company => [
        'name', 'launch_year', 'website', ['category','name']
    ].some(
        key => 
        Array.isArray(key) ?
        String(company[key[0]][key[1]]).toLowerCase().includes(search.toLowerCase()) : 
        String(company[key]).toLowerCase().includes(search.toLowerCase())
    )
);

console.log(results);

Comments

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.