Retrieve the object filtered by a specific group from an array of data

I have a data object that contains various groups and rules within each group item. My task is to filter the rules based on a search query, while also displaying the group name associated with the filtered rule.

{
  "id": "rulesCompany",
  "group": [
    {
      "name": "Cadastral",
      "rule": [
        {
          "title": "Receita Federal",
          "description": "Source updated monthly.",
          "homonym": false,
          "criticality": "high"
        },
        {
          "title": "Primary CNAE - Alteration",
          "description": "Source updated monthly.",
          "homonym": false,
          "criticality": "high"
        }
      ]
    },
    {
      "name": "Modeled Data",
      "rule": [
        {
          "title": "Activity Level - Alteration",
          "description": "Source updated monthly.",
          "homonym": false,
          "criticality": "high"
        },
        {
          "title": "Presumed Revenue",
          "description": "Source updated monthly.",
          "homonym": false,
          "criticality": "medium"
        }
      ]
    }
  ]
}

For instance, if I search for "Rece" in the search field, I should return the group "Cadastral/Receita Federal". However, I am facing challenges in filtering data nested within the object.

Below is what I've implemented so far:

Module.vue

(pre-formatted code block)

Expected Outcome Object when searching for "Rec":

pre-formatted code block

https://i.stack.imgur.com/Fa9qg.png

Answer №1

Here is a computed prop that you can try out:

filteredPolicyRules() {
  if (this.searchQuery) {
    return this.policyRules.group.reduce((groups, { name, rule }) => {
      const rules = [];

      rule.forEach(r => {
        if (r.title.startsWith(this.searchQuery)) {
          rules.push(r);
        }
      });

      if (rules.length > 0) {
        groups.push({
          name,
          rules
        });
      }

      return groups;
    }, []);
  }

  return this.policyRules;
}

I recommend naming them groups and rules (plural) to prevent confusion in the future since they are arrays.

Check out the full demo below:

const policyRules = {
  "id": "rulesCompany",
  "group": [{
    "name": "Cadastral",
    "rule": [{
      "title": "Receita Federal",
      "description": "Updated source monthly.",
      "homonym": false,
      "criticality": "high"
    },
    {
      "title": "Primary CNAE - Change",
      "description": "Updated source monthly.",
      "homonym": false,
      "criticality": "high"
    },
    ]
  },
  {
    "name": "Modeled Data",
    "rule": [{
      "title": "Activity Level - Change",
      "description": "Updated source monthly.",
      "homonym": false,
      "criticality": "high"
    },
    {
      "title": "Presumed Revenue",
      "description": "Updated source monthly.",
      "homonym": false,
      "criticality": "medium"
    }
    ]
  }]
};

new Vue({
  el: '#app',

  data() {
    return {
      searchQuery: '',
      policyRules
    }
  },

  computed: {
    filteredPolicyRules() {
      if (this.searchQuery) {
        return this.policyRules.group.reduce((groups, { name, rule }) => {
          const rules = rule.filter(this.matchFilter);

          if (rules.length > 0) {
            groups.push({
              name,
              rules
            });
          }

          return groups;
        }, []);
      }

      return this.policyRules;
    }
  },

  methods: {
    matchFilter(item) {
      const
        search = this.searchQuery.toLowerCase(),
        term = (item.title || '').toLowerCase();

      return term.includes(search);
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <input v-model="searchQuery" placeholder="Search..." />
  <pre>{{ filteredPolicyRules }}</pre>
</div>

Answer №2

Initially, I stored your list in a variable called map. Then, I filtered this map by searching for the desired properties that contain the specified search term. The array.filter method creates a new array based on the true and false results of the filtering process.

I specifically checked the fields for name, title, and description, making everything lowercase to ensure case insensitivity.

You can refer to Array.prototype.filter documentation for more information.


const searchTerm = 'CNE';

console.log(map.filter(entry => {
  const { name } = entry;
  if(contains(name, searchTerm)) return true;

  for(const rule of entry.rule) {
    const { title, description } = rule;
    if(contains(title, searchTerm)) return true;
    if(contains(description, searchTerm)) return true;
  }
  return false;
}));

function contains(string, term) {
  return string.toLowerCase().includes(term.toLowerCase());
}

I also recommend following Yom's suggestion in his answer to use clearer names like groups and rules, allowing you to improve readability. This would result in

groups.filter(group => {[..]})
and for(const rule of group.rules).

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

Identify the element in the array that corresponds to the current route

Within an array, I have various routes such as: /app/manual/:id /app/manuals/:id /app/feedback ... In my react.js application, I am looking to compare the location.pathname with the paths in my array and retrieve the title associated with the matching pa ...

When the document is shifted by an angular function call, the mouseup event fails to trigger

My problem involves an angular function that alters the ng-if state to display the sidebar when the image is clicked. However, upon calling the function and shifting the entire webpage, the mouseup event for the image no longer triggers when I release th ...

Issue with Axios Response Interceptor on Vuejs causing failure to pass response data

axios.interceptors.response.use( (response) => { return response }, async (error) => { const instance = axios.create({ baseURL: 'myrestbase', timeout: 1000, headers: { 'Authorization': 'Bearer T ...

Having trouble resolving the FancyBox Jquery conflict and unable to find a solution

Attempting to implement FancyBox on a website. The demo is functional, proving its capability. Yet, encountering an error when trying to integrate it within the WordPress theme: Uncaught TypeError: $(...).fancybox is not a function The header file cont ...

What is the best way to access a database connection throughout an entire node.js application?

In my application's app.js file, I establish a connection to mongodb using the monk module. var express = require('express'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var mong ...

When utilizing a third-party library in conjunction with Vuetify, the V-menu may have a tendency to automatically close right after

Incorporating cytoscape into a vuetify SPA has been successful for the most part. The graph renders within a v-card-element, and I can navigate to a different page using the vue router when clicking a note in the graph. However, when attempting to replace ...

JavaScript code returning the correct result, however, it is unable to capture all characters in the returned string

Currently, I am utilizing $.post to retrieve results from a database. The syntax I am using is as follows: $.post('addbundle_summary', {id:id}, function(resultsummary) { alert(resultsummary[0]); }) In CodeIgniter, within my model, I am retu ...

Tips for eliminating whitespace from an input field and then updating the field with the trimmed value

Currently, I am working on email validation where users might input empty spaces in the email field. To address this issue, I have implemented a logic to trim the input value using $trim and then re-assign it to the input field. Although everything seems ...

Adjust the app's color scheme using Vuex's Store functionality

What is the process for transitioning between two color themes associated with a change in language? Languages are switched using the Vuex Store. To ensure the body class changes when the language is changed. State of the story: export default { langu ...

"Utilizing AJAX to dynamically extract data from PHP and manipulate it in a multi-dimensional

Just starting out with JSON/AJAX and I'm in need of some help... I have a PHP page that seems to be returning [{"id":"1"},{"id":2}] to my javascript. How can I convert this data into something more user-friendly, like a dropdown menu in HTML? Here i ...

Modifying the background color and linking it to a different class in Android Studio: A step-by-step guide

Recently, I developed a settings feature for my project that allows users to change the background color. However, I noticed that when I return to the home page, the settings are not saving or syncing properly. Any suggestions on how I can sync this info ...

What steps can be taken to further personalize this pre-existing jQuery sorting solution?

After coming across a solution for adding sorting capabilities to jQuery (source: jQuery sort()), I decided to tweak it to handle strings of variable lengths. Although the modified function sorts in ascending order, I found it quite effective. jQuery.fn.s ...

The IE9 confirmation dialog fails to pause for user response, resulting in automatic postback before user input is received

Behind the Scenes btnNext.Attributes.Add("onclick", " return Verification(this,'" + GetLocalResourceObject("message").ToString() + "'); ") .ASPX Page [Within javascript tags] function Verification(source, message) { var dialog = '< ...

Creating an HTTP request inside an Export Function in a MEANJS application

Initially, I utilized the Yo MeanJs generator to kickstart my project. As a newcomer in the world of MeanJs, things are starting to look quite complex for me. Currently, my MeanJs application is supposed to retrieve data from an HTTP request but, unfortun ...

What method can I use to identify the most widely-used edition of a specific npm module?

While the npm registry does provide metrics on the most depended packages, have you ever wondered if it's possible to determine the most popular version of a specific package? For example, as a user considering upgrading to react-router^4.0.0, wouldn ...

A guide on how to reset Orbit Controls once the target has been defined

After clicking the mouse, I successfully set a new target for my THREE.OrbitControls and it works perfectly. However, once the camera pans to the new location, I lose all mouse interaction. I suspect that I may have broken the controls when I made the came ...

Change the icon switch from fas fa-lock-open to fas fa-lock by adding an event listener for a click action

let lockIcon = document.createElement("i"); lockIcon.setAttribute("class", "fas fa-lock-open"); lockIcon.setAttribute("id", color + "lock"); Is there a way to toggle between the icons fas fa-lock-open and fas fa-lock when clicking using a ...

Erase jQuery from the text

I am struggling with splitting or removing text from a filename. For example, if I have filenames like: 200726100_50-0002.JPG 230514008_60-0001.JPG The desired result should be: 230514008_60.JPG 200726100_50.JPG Am I not using the split function cor ...

What is the best way to update the $scope of a directive from another directive's controller in Angular.js?

One of my directives is responsible for loading a list of events from a service: .directive('appointments', [function () { return { restrict: 'CE', scope: { ngTemplate: '=', ...

What is the best way to establish a two-way connection between two arrays?

Within my application, there is an ItemsService responsible for fetching Items from the server and storing them as JSON objects in its cache. These Items may be displayed in various formats such as tables, graphs, or charts. For instance, when setting up ...