Фильтровать данные внутри массива и возвращает объект, отфильтрованный по группе - PullRequest
2 голосов
/ 08 июля 2019

У меня есть такой объект, и мне нужно отфильтровать правила в каждом элементе группы , однако мне нужно также вернуть имя группы рядом с отфильтрованным правилом

{
  "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"
        }
      ]
    },
  ]
}

enter image description here

Например, мне нужно вернуть группу "Кадастровый / Receita Federal", если я ищу "Rece" вполе поиска, но я не знаю, как фильтровать данные внутри данных.

Что я сделал до сих пор:

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>

Ожидаемый результат объекта с использованием «Rec» в поле поиска:

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

enter image description here

Ответы [ 2 ]

3 голосов
/ 08 июля 2019

Попробуйте эту вычисленную опору.

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;
}

Я бы предложил называть их groups и rules (множественное число) соответственно, чтобы избежать путаницы в будущем - ведь они являются массивами.

Полная демонстрация:

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);
    }
  }
});



  
  {{ filteredPolicyRules }}
1 голос
/ 08 июля 2019

Итак, сначала я поместил ваш список в переменную map.Затем я фильтрую это, проверяя, содержит ли какое-либо из требуемых свойств искомый термин.Метод array.filter возвращает новый массив в зависимости от того, какие записи вернули true, а какие false.

Я проверяю имя, заголовок и описание.Также я сделал все строчными, поэтому регистр не имеет значения.

Array.prototype.filter Ссылка


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());
}

И я бы также предложил, как Йом, в своем ответе вы используете groups и rules, чтобы вы моглиназовите их лучше.Так что тогда будет groups.filter(group => {[..]}) и for(const rule of group.rules)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...