Фильтрация таблицы данных массива из дочернего компонента - PullRequest
0 голосов
/ 10 сентября 2018

Я перевожу одно из своих старых одностраничных приложений PHP / jquery в VueJS / Webpack, пытаясь освоить последнее. Это простая таблица, которая получает свои данные из JSON API и использует элементы управления фильтрами (которые находятся в их собственном компоненте). Все работает, за исключением того, что я пытаюсь отфильтровать свою таблицу, используя элементы управления в моем дочернем компоненте. Я установил опору для массива, который я использую в качестве источника данных для моей таблицы.

Мой App.vue шаблон выглядит так:

<template>
  <div>
      <fan-modals v-bind:fans="fans"></fan-modals>

      <div class="container">
          <filter-controls v-bind:fans="fans"></filter-controls>
          <fans v-bind:fans="fans"></fans>
      </div>  <!-- end #container -->
  </div>
</template>

<script>
  import FilterControls from './components/FilterControls.vue';
  import Fans from './components/Fans.vue';
  import FanModals from './components/FanModals.vue';


  export default {
    name: 'app',
    data: function() {
      return {
        fansUrl: 'example.com',
        fans: []
      }
    },
    components: {
      filterControls: FilterControls,
      fans: Fans,
      fanModals: FanModals
    },
    methods: {
        getFans: function (data) {
            var self = this;
            $.getJSON(self.fansUrl, function(data){
                self.fans = data;
            });
        }
    },
    mounted() {
        this.getFans();
    }
}
</script>

Я пытаюсь повторно использовать свой рефакторированный скрипт jquery, который использовал в моем старом приложении, в функции моего <FilterControls> компонента. Вот фрагмент скрипта моего <FilterControls> дочернего компонента:

<script>
    export default {
        data: function() {
            return {                
                voltageArray: [],
                rpmArray: [],
                noiseLevelArray: [],

                selectedVoltage: 'Voltage',
                selectedRPM: 'Max RPM',
                selectedNoiseLevel: 'Max dBA',

                selectedImpellerSize: '',
                selectedCageSize: '',
                selectedPhase: '',
                selectedFrequency: '',
                secondVoltage: ''
            }
        },
        props: {
            fans: {
                type: Array
            }
        },
        watch: {
            fans(value) {
                this.populateControls(value);
            }
        },
        methods: {
            populateControls(fans) {

                //create emtpy arrays for dropdowns
                var voltage = [];
                var rpm = [];
                var noiseLevel = [];

                //for each fan in fans, get voltages, rpm and noiseLevel values and add them to the empty arrays
                $.each(fans, function(index, value) {
                    voltage.push(fans[index].voltage);
                    rpm.push(fans[index].rpm);
                    noiseLevel.push(fans[index].noise_level);
                });

                //deduplicate and sort arrays
                this.voltageArray = $.unique(voltage).sort();
                this.rpmArray = $.unique(rpm).sort(function(a, b){return a-b});
                this.noiseLevelArray = $.unique(noiseLevel).sort();

            },
             filterFans(fans) {
                var filtered = $.grep(fans, function(fan) {
                   if (this.selectedVoltage === "208-240++") { var secondVoltage = "230"; };

                    return  (selectedImpellerSize === ''    || fan.diameter === selectedImpellerSize);// &&
                            (selectedCageSize === ''            || fan.cage_diameter === selectedCageSize) &&
                            (selectedPhase === ''               || fan.phases === selectedPhase) &&
                            (selectedFrequency === ''           || fan.frequency === selectedFrequency) &&
                            (selectedRPM === 'Max RPM'          || fan.rpm  <= parseInt(selectedRPM)) && 
                            (selectedNoiseLevel === 'Max dBA'   || fan.noise_level <= selectedNoiseLevel) &&
                            (selectedVoltage === 'Voltage'      || fan.voltage === selectedVoltage || fan.voltage === (jQuery.isEmptyObject(secondVoltage) ? selectedVoltage : secondVoltage));
                });

                fans = filtered;
            }
        }
    }
</script>

Метод populateControls() заполняет мои выпадающие списки возможными значениями для фильтрации. Я пытаюсь использовать метод filterFans() для фильтрации моего массива fans, используемого для заполнения моей таблицы. Когда я прикрепляю этот метод к нажатию кнопки, я получаю ошибку:

Uncaught TypeError: Cannot read property 'length' of undefined

Он ссылается на строку, которая начинается var filtered = $.grep(fans, function(fan), поэтому я предполагаю, что у него возникли проблемы с итерацией по моему массиву fans.

Я знаю, что есть лучший способ сделать это, но я очень плохо знаком с VueJS. Я что-то упускаю действительно очевидное?

1 Ответ

0 голосов
/ 11 сентября 2018

Возможно, проблема в использовании привязки обработчика событий кнопки. Например, у вас может быть это:

<button @click="filterFans()">Filter fans</button>

Проблема в том, что отсутствует аргумент функции (т. Е. fans), который требуется filterFans. $.grep пытается прочитать fans.length, что приводит к появившейся ошибке.

Это можно исправить, обновив обработчик в шаблоне:

<button @click="filterFans(fans)">Filter fans</button>

Или обновление filterFans для чтения this.fans напрямую:

filterFans() {
  const filtered = $.grep(this.fans, /* ... */);
}
...