Распространение дочернего элемента к родителю от объекта объектов - PullRequest
0 голосов
/ 22 мая 2019

У меня есть таблица с раскрывающимися списками столбцов, и вместо создания объектов для каждого (то есть данных: {col1: {}, ..}), у меня есть объект объектов, который инициализируется и заполняется на «создан».

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

К вашему сведению, данные таблицы извлекаются через axios. Я использую квазар и вью.

Первоначально у меня был один объект, передаваемый дочерним компонентам, и я мог корректно работать с модификатором синхронизации. Затем перешли к созданию объекта из объектов и переходу к каждому столбцу.

console.log (this.selected) в списке выбора дочерних компонентов печатает пустой.

ПРИМЕЧАНИЕ: это пример, который содержит корневую проблему.

table.vue # parent

<q-table
  row-key="id"
 :tableData
 :columns
 :visible-columns="visibleColumns">
 <q-tr slot="top-row" slot-scope="props">
  <q-td v-for="col in visibleColumns">
   <child-component 
    :selected.sync="dropDownSelected[col]"
    :options="dropDownOptions[col]"
     />
  </q-td>
 </q-tr>
</q-table>

<script>
import ChildComponent from 'path/to/child-component.vue';
export default{
 name: 'table',
 components: {
  'child-component': ChildComponent
 },
 data(){
  return{
    tableData: [{id: 1, col1: 'a', col2: 'b', col3: 'c'}],
    columns: [
     {name: 'col1', label: 'Col1', field: 'col1'},
     {name: 'col2', label: 'Col2', field: 'col2'},
     {name: 'col3', label: 'Col3', field: 'col3'},
    ],
    visibleColumns: ['col1', 'col2'],
    dropDownSelected: {},
    dropDownOptions: {}
  }
 },
 created() {
  this.initializeDropDown();
  this.populateTableSelect();
 },
 methods: {
  initializeDropDown(){
   for(var col in this.columns){
    this.dropDownSelected[col.name] = [];
    this.dropDownOptions[col.name] = [];
   }
  },
  populateTableSelect(){
    // initiallize all columns with new Set
    var tmp_set = {};
    for(var col in this.dropDownOptions){
     tmp_set[col] = new Set();
    }
    // iterate row, add items to set
    for(var row = 0; row < this.tableData.length; row++){
     for(var col in this.dropDownOptions){
      tmp_set[col].add(this.tableData[row][col]);
     }
    }
    for (var col in this.dropDownOptions) {
     tmp_set[col] = [...tmp_set[col]];
     tmp_set[col].sort();
     tmp_set[col] = tmp_set[col].map(item => ({ label: item, value: item }));
     tmp_set[col].unshift({ label: 'Select All', value: 'Select All' });
     this.dropDownOptions[col] = tmp_set[col];
    }
  }
 },
}
</script>

ребенок-component.vue

<q-select
 multiple
 :options="options"
 :value="selected"
 @input="selectionList">
</q-select>

<script>
export default{
 name: 'child-component',
 props: {
  options: {type: Array, required: true},
  selected: {type: Array, default: () => ([])},
  allValue: { type: String, default: 'Select All' }
 },
 methods: {
  selectionList(inputList){
    // logic below used from outside source
    if (inputList.find(item => item === this.allValue)){
     if(this.selected.find(item => item === this.allValue)){
      // case 1: one item is unchecked while 'all' is checked -> unchecks 'all' + keep other
      inputList.splice(inputList.indexOf(this.allValue), 1);
      this.$emit('update:selected', inputList);
     }
     else {
      // case 2: 'all' is checked -> select-all
      this.$emit('update:selected', this.options.map(option => option.value));
     }
    }
    else {
     if(this.selected.find(item => item === this.allValue)){
     // case 3: unchecking 'all' -> clear selected
      this.$emit('update:selected', []);
     }
     else{
      if(inputList.length === this.options.length -1){
       // case 4: len is equal to options -> select-all
       this.$emit('update:selected', this.options.map(option => option.value));
      }
      else {
       // case 5: check an item
       this.$emit('update:selected', inputList);
      }
     }
    }
   },
 },
}
</script>

Я ожидал, что передача объекта из объекта объектов позволила бы логике «Выбрать все» распространяться к родителю.

Я не вижу никаких ошибок, поэтому понятия не имею, что делает js.

1 Ответ

0 голосов
/ 22 мая 2019

Из того, что я вижу, это простая проблема реактивности, объясненная в документации .dropDownOptions и dropDownSelected - это объекты, для которых вы добавляете новые ключи.Каждый раз, когда вы делаете это, вам нужно звонить this.$set.

. Я думаю, что если вы только измените этот метод, вы должны быть хороши:

initializeDropDown(){
  for(var col in this.columns){
    this.$set(this.dropDownSelected, col.name, []);
    this.$set(this.dropDownOptions, col.name, []);
  }
},
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...