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

Struggling with sending a post request in Node.js as the response always returns with an empty body

Here is the structure of my project And this error pops up when I run my program using npm run dev command I'm working on a basic webpage where users can input their name, email, and job details. I then try to insert this information from the HTML fo ...

Showing JSON information fetched from an AJAX request within an HTML page

I've been working on a project and I'm almost there with everything figured out. My main challenge now is to display an array of items on a web page after making an ajax call. Below is the code snippet I currently have: JQuery Code: var su ...

Incorporating unique symbols into a RegExp object during its creation using a variable

As a beginner, I am currently working on a small function that will allow users to pick up objects and add them to an inventory by entering text in a box. In my setup, there is a text box with the id "commandBox" and a button that triggers the 'pickU ...

Adaptable material for collapsible panels

I'm facing a challenge with implementing an accordion menu. My goal is to have a 4 column layout that transforms into an accordion menu when the browser width is less than 600px. It almost works as intended, but there's a glitch. If you start at ...

What is the process for implementing text box validation on a button click within a gridview in asp.net utilizing javascript?

How can I implement textbox blank validation on button click within a gridview using JavaScript? My gridview has multiple rows with 2 textboxes and a save button in each row. I need to validate the textboxes when their corresponding save button is clicked. ...

Using TypeScript to consolidate numerous interfaces into a single interface

I am seeking to streamline multiple interfaces into one cohesive interface called Member: interface Person { name?: { firstName?: string; lastName?: string; }; age: number; birthdate?: Date; } interface User { username: string; emai ...

Tips on using the $.grep() method in jQuery to filter dynamic inputs

When using the "grep" function in jQuery to filter data, the code sample below works well for static conditions. However, if the "name" and "school" parameters have multiple values, how can we filter them? Let's say I receive the name and school from ...

The `<Outlet/>` from react-router is being rendered in a location outside of its intended wrapper div

Utilizing MUI for crafting a straightforward dashboard featuring an <AppBar>, a side <Drawer>, my component appears as follows: <> <AppBar> // code omitted <AppBar/> <Drawer> // code omitted <Drawer/> / ...

"Utilizing the power of ng-click to target specific child

I am facing an issue with my owl carousel where events are not firing on cloned items. In search of a solution, I came across a suggestion from Stack Overflow to move the event handler from the direct target to its parent element: Original code snippet: ...

What is the best way to assign a value to a property in a Controller or Global Variable using jQuery?

On my ASP MVC 5 site, I have a checkbox within the NavBar element. This checkbox's state dictates whether or not the Grid will display Inactive records alongside active ones on each page. In an attempt to have all controllers access the same property ...

Retrieve the chosen item from the autocomplete feature

Unfortunately, I have encountered an issue with this solution as I was unable to get it to work correctly in my code. The objective is to retrieve the selected item and then call another function to utilize it. The script is as follows: <script type=" ...

Looking to include a data-* attribute within a div element for the utilization of a third-party JavaScript library like React or Next.js?

let speed = '{ "speed": 0.2 }'; <div className="section jarallax h-100vh" data-jarallax={speed} style={{backgroundImage: "url('/images/header-bg.jpg')"}} id="home"> </div> <Script src="./js/parallax.js" strate ...

Tips for styling cells in a certain column of an ng-repeat table

I am currently facing an issue with a table I have created where the last column is overflowing off the page. Despite being just one line of text, it extends beyond the right edge of the page without being visible or scrollable. The table is built using th ...

javascript/jquery: ensure Android device displays content in full-screen mode

Currently working on developing a web app specifically for an android device that needs to be displayed in fullscreen mode. I came across the code snippet above on stack overflow, which successfully activates fullscreen mode upon click event. However, I a ...

Trouble with firing the click event using document.createElement('a') in Firefox

I wrote a function that fetches arraybuffer data from my API, generates a temporary anchor element on the webpage, and then triggers a click event to download the file. Interestingly, this function performs as expected in Chrome. @action async loadVouc ...

Ordering a multi-level array in PHP with string numerical values

I am currently developing a ticket system using Zend Framework and facing a challenge in sorting the tickets based on their status, which is stored as a string. Here is an example of how each entry in my array looks: `[1] => array(14) { ["ticket_i ...

methods for efficient set computations

I have a collection of sets in the format (a,b) which are as follows: (2,4) (1,3) (4,5) (1,2) If I am given a pair like <2,1>, I want to identify all sets in the collection where 2 or 1 is the first element. In this case, it would be (2,4), (1,3), ...

Customize the appearance of the bootstrap nav-bar by assigning unique background colors to each dropdown menu

I'm looking to set unique background colors for each dropdown in a Bootstrap nav-bar using CSS. .mynavbar .dropdown ul.dropdown-menu:nth-child(1) { background-color: #59b057; } .mynavbar .dropdown ul.dropdown-menu:nth-child(2) { background-col ...

Unlocking the potential of resizable bootstrap table columns in React

Currently utilizing a bootstrap table <div class="table-responsive"> <table class="table table-bordered"> <thead> <tr> <th>#</th> <th>Table heading</th> </tr> < ...

What steps can be taken to address the JavaScript error that states: Error : TypeError: $("j2t-temp-div").down(".j2t_ajax_message") is not defined?

If you want to see the issue in action, please visit this link. To replicate this error, choose a "Color" and "Size", then click "Add to Cart". While the "loading..." dialog box is still visible, click on the shade to close it. Quickly click on any other ...