Sorting through names within a nested array based on specific criteria

I have been struggling to filter by item name for the past day and haven't been successful. The issue lies in my attempt to use a sample array for filtering. While I am able to filter by category successfully, the same cannot be said for filtering by item to display only matching items. Essentially, I have a computed property that is linked to my search input. Although I can retrieve all items, the filtering does not work as expected when a character is entered.

Here is an example of my markup:

<div class="col-3 mb--20">
        <div class="input-group-over pl--10 round">
            <input v-model="search" type="text" class="form-control form-control-sm iqs-input" data-container=".iqs-container" value="" placeholder="Search">
            <span class="fi fi-search btn btn-sm pl--12 pr--12 text-gray-500"></span>
        </div>
    </div>

 <div v-for='(cat, index) in menu' :key="index">
        <h5 class="text-left m-4"><b>{{cat.name}}</b></h5>
        <div class="row">
            <div v-for='(item, index2) in cat["items"]' :key="index2" class="col-lg-6 col-md-12 mt-2">
                <div class="col-12 border pointer">
                    <div @click="test" class="p-2">
                        <div class="d-flex justify-content-end">
                            <span class="mr-auto"><b>{{item.name}}</b></span>
                            <span><b>${{item.price}}</b></span>
                        </div>
                        <div class="text-left text-muted pt-1">
                            <div class="d-flex justify-content-start">
                                <img :src="item.img" class="img-fluid pr-3" alt="">
                                <span class="crop-text">{{item.desc}}</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

This is the sample array:

const m = {
  "menu": [
    {
      "categories": 
      [
        {
          "name": "Black Angus Burgers",
           ...
                         

Function snippet:

computed: {
        menu() {
            //  console.log(store.state.menu)
            return m.filter((doc) => {
                try {
                    return doc
                        .items
                        .some
                        .name
                        .toLowerCase().match(this.search.toLowerCase())
                } catch (err) {
                    console.log(err)

                }
            })
        `
    }

Thank you for your help!

Answer №1

Below is a code snippet that you can try out:

UPDATE

Vue implementation:

const menu = {
  menu: [
    {
      categories: [
        {
          name: "Black Angus Burgers",
          position: 1,
          id: 1,
          items: [
            {
              desc:
                'Bring home the bacon, but make sure that bacon is hickory smoked and on top of cheddar and 1/3 lb. of chargrilled Black Angus beef.  This burger"s name explains itself. Of course, you can also top it with crisp lettuce, tomatoes and anything else.',
              img:
                "https://s3.amazonaws.com/backyardburgers.com/Burgers/updated/bacon-cheddar-burger.png?mtime=20160801105417",
              name: "1/3 lb Bacon Cheddar Burger",
              price: 11
            },
            // Other burger items go here...
          ]
        },
        // Other categories go here...
      ]
    }
  ]
};

// Vue app instantiation
var app = new Vue({
  el: "#app",
  data: {
    menu,
    search: ""
  },
  computed: {
    appMenu() {
      if (this.search.trim().length) {
        return this.menu.menu[0].categories.map(doc => {
          const items = doc.items.filter(item => {
            return item.name.match(new RegExp(`${this.search}`, 'i'));
          });
          return { ...doc, items };
        }).filter(({ items }) => items.length > 0);
      } else {
        return this.menu.menu[0].categories;
      }
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div class="col-3 mb--20">
    <div class="input-group-over pl--10 round">
      <input v-model="search" type="text" class="form-control form-control-sm iqs-input" data-container=".iqs-container" value="" placeholder="Search">
      <span class="fi fi-search btn btn-sm pl--12 pr--12 text-gray-500"></span>
    </div>
  </div>

  <div v-for='(cat, index) in appMenu' :key="index">
    <h5 class="text-left m-4"><b>{{cat.name}}</b></h5>
    <div class="row">
      <div v-for='(item, index2) in cat["items"]' :key="index2" class="col-lg-6 col-md-12 mt-2">
        <div class="col-12 border pointer">
          <div class="p-2">
            <div class="d-flex justify-content-end">
              <span class="mr-auto"><b>{{item.name}}</b></span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Answer №2

Here is the information you were looking for. If it's not exact, it should be close enough for you to customize as needed.

const menuOptions = {
      options: [
        {
          categories: [
            {
              name: "Delicious Burgers",
              position: 1,
              id: 1,
              items: [
                {
                  desc:
                    'Treat yourself to a mouthwatering burger topped with hickory smoked bacon, cheddar cheese, and a juicy 1/3 lb. Black Angus beef patty. Customize it with your favorite toppings for the perfect meal.',
                  img:
                    "https://example.com/bacon-cheddar-burger.png",
                  name: "Bacon Cheddar Burger",
                  price: 11
                },
                // Other burger options go here...
              ]
            },
            // Other food categories go here...
          ]
        }
      ]
    };

var app = new Vue({
  el: "#app",
  data: {
    menuOptions: menuOptions,
    searchQuery: ""
  },
  computed: {
    filteredMenu() {
      if(this.searchQuery.trim() === "") {
          return this.menuOptions.options[0].categories;
      }
      return this.menuOptions.options[0].categories.map(cat => {
        const newItems = cat.items.filter(item => {
             return item.name.toLowerCase().includes(this.searchQuery.toLowerCase());
         });
        return {...cat, items: newItems };
      });
    }
  }
});
img { width: 20px; height: 20px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div class="col-3 mb--20">
    <div class="input-group-over pl--10 round">
      <input v-model="searchQuery" type="text" class="form-control form-control-sm iqs-input" data-container=".iqs-container" value="" placeholder="Search">
      <span class="fi fi-search btn btn-sm pl--12 pr--12 text-gray-500"></span>
    </div>
  </div>

  <div v-for='(category, index) in filteredMenu' :key="index">
    <h5 class="text-left m-4"><b>{{category.name}}</b></h5>
    <div class="row">
      <div v-for='(item, index2) in category["items"]' :key="index2" class="col-lg-6 col-md-12 mt-2">
        <div class="col-12 border pointer">
          <div class="p-2">
            <div class="d-flex justify-content-end">
              <span class="mr-auto"><b>{{item.name}}</b></span>
              <span><b>${{item.price}}</b></span>
            </div>
            <div class="text-left text-muted pt-1">
              <div class="d-flex justify-content-start">
                <img :src="item.img" class="img-fluid pr-3" alt="">
                <span class="crop-text">{{item.desc}}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Answer №3

This particular approach centers on data filtration by implementing filters based on categories and a search term. It exclusively displays those categories that have items matching the search term, as well as the specific items within each category that also match the term.

The Vue functionality for other code remains untouched, although it is advisable to handle it separately.

const filterCategories = (categories, searchTerm) =>
  categories .map (({items, ...rest}) => ({
    ...rest,
    items: items .filter (({desc}) => desc .toLowerCase () .match (searchTerm .toLowerCase ()))
  })) 
  .filter (({items}) => items .length > 0)

const categories = [{name: "Black Angus Burgers", position: 1, id: 1, items: [{desc: 'Bring home the bacon, but make sure that bacon is hickory smoked and on top of cheddar and 1/3 lb. of chargrilled Black Angus beef.  This burger"s name explains itself. Of course, you can also top it with crisp lettuce, tomatoes and anything else.', img: "https: //s3.amazonaws.com/backyardburgers.com/Burgers/updated/bacon-cheddar-burger.png?mtime=20160801105417", name: "1/3 lb Bacon Cheddar Burger", price: 11}, {desc: "A classic burge...
  }));</answer3>
<exanswer3><div class="answer" i="60819328" l="4.0" c="1584976392" a="U2NvdHQgU2F1eWV0" ai="1243641">
<p>This response is dedicated solely to filtering data based on categories and a specified search term. It focuses on presenting only those categories that contain relevant items matching the search term, while also showcasing the corresponding items within each matched category.</p>

<p>The handling of Vue in relation to other code segments has been left intact; however, it is advised to manage them separately.</p>

<p><div>
<div>
<pre class="lang-js"><code>const filterCategories = (categories, searchTerm) =>
  categories .map (({items, ...rest}) => ({
    ...rest,
    items: items .filter (({desc}) => desc .toLowerCase () .match (searchTerm .toLowerCase ()))
  })) 
  .filter (({items}) => items .length > 0)

const categories = [{name: "Black Angus Burgers", position: 1, id: 1, items: [{desc: 'Bring home the bacon, but make sure that bacon is hickory smoked and on top of cheddar and 1/3 lb. of chargrilled Black Angus beef.  This burger"s name explains itself. Of course, you can also top it with crisp lettuce, tomatoes and anything else.', img: "https: //s3.amazonaws.com/backyardburgers.com/Burgers/updated/bacon-cheddar-burger.png?mtime=20160801105417", name: "1/3 lb Bacon Cheddar Burger", price: 11}, {desc: "A classic burger just like dad used to make. That is, if your dad was a crowd-pleasing grillmaster who used Black Angus beef topped with garden-fresh lettuce, lush tomatoes and crunchy dill pickles. Apologies to dads everywhere.", img: "https: //s3.amazonaws.com/backyardburgers.com/Burgers/updated/classic-burger.png?mtime=20160801105924", name: "Back Yard Classic Burger", price: 9}, {desc: "How do you improve a classic? Double it. Twice as much Black Angus beef as our Classic burger with the same mouthwatering fixings. Grab a few extra napkins for this one. This burger is big.", img: "https: //s3.amazonaws.com/backyardburgers.com/Burgers/JPGs/Screen-Shot-2016-07-05-at-3.04.40-PM.png?mtime=20160801110322", name: "Back Yard Double Classic Burger", price: 7}, {desc: "Sauted mushrooms. Creamy Swiss. Black Angus beef. Mouth. Now. Wait, wait, wait. Before you do, top it with fresh lettuce and tomatoes. Or top it with anything else you want. It’s your burger.", img: "https: //s3.amazonaws.com/backyardburgers.com/Burgers/JPGs/mush-swiss-burger.png?mtime=20160801110114", name: "Mushroom Swiss Burger", price: 10}, {desc: "The ace up our sleeve, dealt to your hands, no bluffing and this metaphor has gone on too long. No tricks here. Our Black Jack Burger is topped with pepper jack cheese and zesty creole mayo. Grill-blackened Angus with a kick. Your move.", img: "https: //s3.amazonaws.com/backyardburgers.com/Burgers/JPGs/Screen-Shot-2016-07-05-at-3.00.40-PM.png?mtime=20160721140930", name: "Black Jack Burger", price: 9}, {desc: "Sweet. Baby. Rays!, dad proclaimed after a single burger bite. The savory stack of Black Angus beef, chipotle mayo, cheddar, smoky bacon, crispy onion straws, tomato and pickles. Oh, and Sweet Baby Rays BBQ sauce. Maybe that's why he said it.", img: "https: //s3.amazonaws.com/backyardburgers.com/Burgers/updated/chipotle-burger.png?mtime=20160801105822", name: "Chipotle Burger", price: 8}, {desc: "What’s Black Angus beef and bleu all over? This burger. Crumbled bleu cheese and smoky bacon top this mouthwatering concoction straight from the classic black and bleu inspiration well.", img: "https: //s3.amazonaws.com/backyardburgers.com/Burgers/JPGs/black-and-blue-burger.png?mtime=20160801110500", name: "Black and Bleu Burger", price: 6}, {desc: "It’s like someone pointed a shrink ray at one of our classic burgers, but somehow kept the classic taste. Science? Magic? Skynet! No, no. Our chefs just know how to deliver big, bold flavor in any size.", img: "https: //s3.amazonaws.com/backyardburgers.com/Burgers/updated/picnic-burger.png?mtime=20160801104952", name: "Picnic Burger", price: 9}]}, {name: "Turkey & More", position: 2, id: 2, items: [{desc: "Blackened chicken met creamy slaw and they fell in love. Now you can eat their love complete with perfectly ripe tomatoes. This chicken sandwich is spicy and zesty and waiting for you to order it already.", img: "https: //s3.amazonaws.com/backyardburgers.com/Turkey-Chicken-Veggie/BYB-BlackenedChickenSandwich.jpg?mtime=20160801112514", name: "Blackened Chicken Sandwich", price: 9}, {desc: "Blackened chicken. Pepper Jack cheese. Bacon. Creole mayo. No, we aren’t bluffing. This sandwich was made for you. That is, if you’re the type who likes a little kick to their chicken sandwich.", img: "https: //s3.amazonaws.com/backyardburgers.com/Turkey-Chicken-Veggie/BYB-BlackJackChickenClub.jpg?mtime=20160721141133", name: "Black Jack Chicken Club", price: 11}, {desc: "A chicken classic. No, not the “cross the road” joke dad always tells. We’re talking about this seasoned, chargrilled-to-juicy-perfection Grilled Chicken Sandwich. It’s so good you can tell your dad the chicken crossed the road to be a part of it.", img: "https: //s3.amazonaws.com/backyardburgers.com/Turkey-Chicken-Veggie/BYB-GrilledChickenSandwich.jpg?mtime=20160721141131", name: "Grilled Chicken Sandwich", price: 6}, {desc: "The only thing tender about these big and bold Chicken Tenders is, well, everything. Our juicy, tender white chicken is covered with crunchy yet fluffy breading you’ll want to bite into again and again.", img: "https: //s3.amazonaws.com/backyardburgers.com/Burgers/updated/kids-meal-chicken.png?mtime=20160729142142", name: "Chicken Tenders", price: 10}, {desc: "Who are you calling a turkey? Oh, our Classic Turkey Burger? Well, ok then. Top this char-grilled turkey with crisp lettuce, fresh tomato and mayo and we won’t have a problem. Or put whatever you want on it, we’re pretty laid back.", img: "https: //s3.amazonaws.com/backyardburgers.com/Burgers/updated/classic-turkey-burger.png?mtime=20160801111120", name: "Classic Turkey Burger", price: 6}, {desc: "Charbroiled chicken breast hand-dipped in Hawaiian sauce then topped with freshly grilled pineapple, mustard and crisp lettuce. This sandwich has enough Hawaiian flavor packed in without you wearing a hula skirt to eat it, dad.", img: "https: //s3.amazonaws.com/backyardburgers.com/Turkey-Chicken-Veggie/BYB-HawaiianChickenSandwich.jpg?mtime=20160721141131", name: "Hawaiian Chicken Sandwich", price: 10}, {desc: "Aaaaaaaand the crowd goes wild…for this burger…made of turkey. Seriously. The Pepper Jack cheese. The creole mayo. The tangy mustard. It all comes together on this sandwich built to please turkey burger lovers and doubters alike.", img: "https: //s3.amazonaws.com/backyardburgers.com/Turkey-Chicken-Veggie/BYB-WildTurkeyBurger.jpg?mtime=20160721141131", name: "Wild Turkey Burger", price: 8}, {desc: "The best of the ballpark is now at the Back Yard. We decided to forgo the classic ketchup and mustard for something a little hotter and a whole lot meatier, and topped it off with some ooey gooey cheddar cheese. We think it’s a home run.", img: "https: //s3.amazonaws.com/backyardburgers.com/BYB-ChiliCheeseDog_BurntBun.jpg?mtime=20190325101810", name: "Chili Cheese Hot Dog", price: 5}, {desc: "The humble, back yard legend:  a juicy all-beef hot dog grilled on an open flame. Topped with ketchup, mustard, and relish.", img: "https: //s3.amazonaws.com/backyardburgers.com/BYB_HotDog_012.jpg?mtime=20190522104045", name: "Back Yard Hot Dog", price: 11}]}, {name: "Salads & Veggie Options", position: 3, id: 3, items: [{desc: "For a place that serves so much beef, you’d think we forgot about a veggie burger. You’d be sadly mistaken, veggie man or veggie woman! Top yours with lettuce, tomato, red onion, pickles, mustard and/or ketchup.", img: "https: //s3.amazonaws.com/backyardburgers.com/Turkey-Chicken-Veggie/VeggieBurger-RegularBun.jpg?mtime=20160721141034", name: "Veggie Burger", price: 10}, {desc: 'We start with a fresh lettuce base and add tomatoes, red onion, bacon, blue cheese crumbles, candied pecans, dried cranberries, and croutons. Add Grilled, Fried or Blackened Chickn. This salad is one you don"t want to miss.', img: "https: //s3.amazonaws.com/backyardburgers.com/Hot-Dogs-Sides/Salads/Chopped-Salad.JPG?mtime=20160721141226", name: "Cranberry Pecan Chicken Salad", price: 11}, {desc: "Fried, Grilled or Blackened — choose your chicken and we’ll lay it on a bed of fresh lettuce, sharp red onions, vine-ripened tomatoes and sliced cucumbers.", img: "https: //s3.amazonaws.com/backyardburgers.com/Hot-Dogs-Sides/Salads/BYB-ChickenSalad.jpg?mtime=20160721141227", name: "Back Yard Chicken Salad", price: 10}, {desc: "Dive in to fre...

console.log ('*** With `tender` ***')
console.log (filterCategories (categories, 'tender'))

console.log ('*** With `mustard` ***')
console.log (filterCategories (categories, 'mustard'))
.as-console-wrapper {min-height: 100% !important; top: 0}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using jQuery to show/hide linked CSS3 animations upon Mouseenter/Mouseleave events

Exploring the capabilities of animate.css and jQuery within a bootstrap environment has been quite interesting for me. However, I've encountered a major issue! I am attempting to trigger animations on mouseenter / mouseleave, which led me to create a ...

Enhance the color scheme of your collapsed or expanded Bootstrap NAV for mobile devices

Currently working on customizing the navbar using Bootstrap. I've been able to style it perfectly for both desktop and mobile devices in its initial state. The issue arises when attempting to style the navbar in its expanded and collapsed states on m ...

Is it possible to incorporate npm modules into a browser and utilize them locally on a personal computer?

This is my first time working with npm modules and node.js, so I find it quite challenging. I have a JavaScript code with multiple data points and I need to find the closest city to each of them. In response to another question on Stack Overflow (Reverse ...

vue-chartjs is experiencing difficulties when it comes to showing the labels and datasets

I'm having an issue with my line-chart. The data from the api/controller isn't showing up on the chart, even though the response contains all the data. https://i.stack.imgur.com/PWZxZ.png As shown in the image, the line-chart is empty but the r ...

Looking to Identify a Click Within a Complicated Component and Retrieve the Component's ID

Currently, I am working with React for development and have a need to capture clicks at the topmost parent level for performance reasons. const clickHandler = (e) => { console.log("clickHandler", e.target) --> I want to identify the child ...

Incorporating the outcome of "data" or "methods" into a VueRouter prop

Looking for a solution to my menu tabs router issue: Tab 1 | Tab 2 | Tab 3 Each tab has its own route attached to a specific component. For example: const router = new VueRouter({ routes: [ { path: '/views/type1', component: Type1, props ...

Adding a number repeatedly and showing the result

I have been searching for a solution to this particular problem for quite some time now, but unfortunately, I haven't been able to find one yet. It would be incredibly helpful if someone could guide me in the right direction. Let's say we start ...

Using localStorage in the client side of nextJS is a breeze

Encountering an error while attempting to retrieve local storage data. Even with the use client directive in place at the beginning, the issue persists. 'use client'; const baseURL = 'https://localhost:7264'; const accessToken = localSt ...

What is the best way to choose all elements that fall between two specific elements?

Looking to grab content situated between two specific elements within an HTML structure. The HTML snippet in question is as follows... <h2>This is firsty</h2> <p>Some para</p> <ul> <li>list items</li> <li&g ...

What is the most efficient way to dynamically alter the position of a div element within an HTML document using

In a scenario where a parent div contains multiple child divs, it is required that one particular child div named .div_object_last always stays at the end. Below is an example setup : HTML <div class="div_parent"> <div class="div_object"> ...

Toggling with Jquery when an image is clicked

I'm trying to wrap my head around the functionality of jquery toggle. My goal is to toggle to the next anchor element with the class plr-anchor when an image with the class go_down is clicked. The information is being populated using maps. Javascript ...

What is the process for adding a download link to my canvas once I have updated the image?

Is it possible to create a download link for an image that rotates when clicked, and then allows the user to download the updated image? Any help would be appreciated.////////////////////////////////////////////////////////////////////// <!DOCTYPE ht ...

What is the best way to divide a string into an array containing both linked and non-linked elements?

I'm struggling to find the right solution to my problem. I need to create a view that is enclosed in a clickable div. The content will consist of plain text mixed with clickable URLs - the issue arises when clicking on a link also triggers the method ...

Exploring the functionality of Array.prototype.includes() in Angular 7 with PhantomJS testing

While testing components in my Angular application, I noticed that unit tests utilizing Array.prototype.includes() are successful in Chrome but fail when executed with PhantomJS. I found some suggestions in the responses to this question related to a simi ...

Using the first value of an array as a unique key and the second value as its corresponding values on a new array

Below is an array structure: $array1 = array 0 => array 0 => string 'biodata' (length=7) 1 => string 'family_name' (length=11) 1 => array 0 => string 'bi ...

Instructions on adjusting the image size within a MUI Card

import { Card, CardActionArea, CardContent, CardMedia, Typography, } from "@mui/material"; import React from "react"; import { styled } from "@mui/material/styles"; const CardImage = styled("div")(({ theme ...

npm package.json scripts not executing

Whenever I try to run npm start or npm run customScriptCommand, npm seems to not be executing anything on my project and just quickly returns a new line in the terminal. I attempted to solve this issue by uninstalling node and npm from my machine, then in ...

What is the best way to prompt users to submit comments with a popup textarea box?

Within my project, I have incorporated a dropdown list: <div class="dropdown"> <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Select subject <span class="caret"></span> </but ...

Getting data before the Router is loaded following authentication with Angular 2+ - A comprehensive guide

I'm hoping this isn't a repeat. Within my login component, I have a feature that allows users to log in, which calls a service and retrieves a Token. Upon successful login, the token is saved to localStorage. Subsequently, I use the getUserData ...

Ways to incorporate a smooth transition between the opened and closed fab functionality

I am currently utilizing VueJS and Vuetify in my project. I have successfully implemented Vuetify's FAB component, which displays a list of fab buttons as demonstrated in the documentation: <div id="fab-button"> <v-speed-dial v-mo ...