简体   繁体   中英

Filter data inside array and returns object filtered with group

I have an object like this and I need to filter the rules within each group item , however I need to also return the group name next to the filtered rule

{
  "id": "rulesCompany",
  "group": [
    {
      "name": "Cadastral",
      "rule": [
        {
          "title": "Receita Federal",
          "description": "Fonte atualizada mensalmente.",
          "homonym": false,
          "criticality": "high"
        },
        {
          "title": "CNAE Primário - Alteração",
          "description": "Fonte atualizada mensalmente.",
          "homonym": false,
          "criticality": "high"
        },
      ]
    },
    {
      "name": "Dados modelados",
      "rule": [
        {
          "title": "Nível de Atividade - Alteração",
          "description": "Fonte atualizada mensalmente.",
          "homonym": false,
          "criticality": "high"
        },
        {
          "title": "Faturamento Presumido",
          "description": "Fonte atualizada mensalmente.",
          "homonym": false,
          "criticality": "medium"
        }
      ]
    },
  ]
}

在此处输入图片说明

For example, I need to return the group "Cadastral/Receita Federal" if I search for "Rece" in search field, but I don't know how to filter data inside data.

What I've done so far:

Module.vue

<template>
  <div>
    <slide-out :visible.sync="isVisible" :title="text.header">
      <div slot="header">
        <div>
          <button class="neo-bt-icon--big slideout__close--button" @click="isVisible=false">
            <svg><use xlink:href="/red/neo-assets/images/simple-line-icons.svg#arrow-2-left"></use></svg>
          </button>
          <h1 class="slideout__header--text">
            {{ text.header }}
          </h1>
          <div class="neo-form-toggle-list__item neo-form-toggle neo-form-toggle--checkbox">
            <input type="text" class="neo-form-field" placeholder="Buscar" v-model="searchQuery">
            <input class="neo-form-toggle__field" :id="selectAllRules" @click="selectAllRules($event)" type="checkbox"/>
            <label class="neo-form-toggle__label" :for="selectAllRules">selecionar tudo</label>
          </div>
        </div>
      </div>
      <div slot="content">
        <div v-for="policyRule in filteredPolicyRules.group" :key="policyRule.name"
          class="neo-form-group">
          <li v-text="policyRule.name"></li>
          <div class="neo-form-toggle-list__item neo-form-toggle neo-form-toggle--checkbox">
            <input class="neo-form-toggle__field" :id="policyRule.name" @click="selectGroupRules(policyRule.rule, policyRule.name, $event)" type="checkbox" v-model="policyRules.name" />
            <label class="neo-form-toggle__label" :for="policyRule.name">selecionar grupo</label>
          </div>
          <div class="neo-form-toggle-list neo-form-toggle-list--inline">
            <div v-for="rule in policyRule.rule" :key="rule.title"
              class="neo-form-toggle-list__item neo-form-toggle neo-form-toggle--checkbox">
              <input class="neo-form-toggle__field" :id="rule.title" :value="rule" name="rule" type="checkbox" v-model="checkedRules"/>
              <label class="neo-form-toggle__label" :for="rule.title">{{ rule.title }}</label>
              <h6 class="neo-text-disabled-options">{{ rule.description }}</h6>
            </div>
          </div>
        </div>
      </div>
      <div slot="footer">
        <span>{{ checkedRules  }}</span>
      </div>
    </slide-out>
  </div>
</template>

<script>
import { mapState } from 'vuex';

import SlideOut from '@/components/shared/slideout/SlideOut.vue';

export default {

  name: 'ModulePolicyRules',
  props: [],
  components: {
    SlideOut,
  },
  data() {
    return {
      isVisible: false,
      policyRules: [],
      searchQuery: '',
      checkedRules: [],
      filteredRules: [],
    };
  },
  computed: {
    filteredPolicyRules() {
      const me = this;
      if (this.searchQuery) {
        me.filteredRules.pop();
        this.policyRules.group.filter((ruleGroup) => {
          ruleGroup.rule.forEach((rule) => {
            if (rule.title.startsWith(this.searchQuery)) {
              console.log(me.filteredRules);
              me.filteredRules.push(rule);
            }
          });
        });
        console.log(me.filteredRules);
        return me.filteredRules;
        // return this.policyRules.group.filter(item => item.name.startsWith(this.searchQuery));
      }
      return this.policyRules;
    },
  },
  methods: {
    async loadData() {
      const rules = await this.$store.dispatch('policyrules/setPolicyRules');
      this.policyRules = rules;
    },
  },
  mounted() {
    this.loadData();
  },
};
</script>

<style lang="scss">
  .neo-form-toggle__label {
    text-transform: none;
    font-weight: 600;
  }

  .neo-text-disabled-options {
    text-transform: none;
  }
</style>

Object expected result using "Rec" in search field:

{
  "name": "Cadastral",
  "rule": [
    {
      "title": "Receita Federal",
      "description": "Fonte atualizada mensalmente.",
      "homonym": false,
      "criticality": "high"
    },
  ]
},

在此处输入图片说明

Try this computed prop.

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'd suggest calling them groups and rules (plural) respectively, to avoid future confusion -- after all they are arrays.

Full demo:

 const policyRules = { "id": "rulesCompany", "group": [{ "name": "Cadastral", "rule": [{ "title": "Receita Federal", "description": "Fonte atualizada mensalmente.", "homonym": false, "criticality": "high" }, { "title": "CNAE Primário - Alteração", "description": "Fonte atualizada mensalmente.", "homonym": false, "criticality": "high" }, ] }, { "name": "Dados modelados", "rule": [{ "title": "Nível de Atividade - Alteração", "description": "Fonte atualizada mensalmente.", "homonym": false, "criticality": "high" }, { "title": "Faturamento Presumido", "description": "Fonte atualizada mensalmente.", "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> 

So first I've put your list into a map variable. Then I'm filtering that by checking if any of the wanted properties contain the search term. The array.filter Method returns a new array based on what entries returned true and what false.

I'm checking inside name, title and description. Also I made everything lower case so case doesn't matter.

Array.prototype.filter Reference


const term = 'CNE';

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

  for(const _r of e.rule) {
    const { title, description } = _r;
    if(contains(title, term)) return true;
    if(contains(description, term)) return true;
  }
  return false;
}));

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

And I would also suggest like Yom in his answer that you use groups and rules so you can name them better. So that then would be groups.filter(group => {[..]}) and for(const rule of group.rules)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM