Hello. Help deal with vuejs. The essence of the task: there is a grid, in each cell there is a button "add element", by its pressing a modal window pops up with select. After selecting the desired parameter in the modal. The "add" button is clicked in the window and a div should appear in the same cell with the name of the selected element (in brief)

Principle of operation: grid, cell, button, modal. The window is a separate component. In the grid there is an array storing all added elements for the whole grid. Each cell has its own id, which is added. In modal. The window triggers an event by clicking on the button, it causes an event at the button, a button at the cell, a cell at the grid, and the grid sends the cell a complete list of all added elements :)

Pieces of code:

Grid:

<template> <div> {{ elements }} <table class="table table-bordered"> <tr> <cell id="one" :onAdded="addElement" :elements="elements"></cell> <cell id="two" :onAdded="addElement" :elements="elements"></cell> </tr> </table> </div> </template> <script> export default { data: function() { return { elements: {} }; }, methods: { addElement: function(cellId, name) { console.log('В ячейку', cellId, 'нужно добавить элемент', name); let elements = this.elements; if(typeof elements[cellId] === 'undefined') elements[cellId] = []; elements[cellId].push({name}); this.$set(this.elements, elements); } } </script> 

Cell:

 <template> <td> <div class="panel panel-default" v-if="typeof elements[id] !== 'undefined'" v-for="element in elements[id]" > {{ element.name }} </div> <add-element-button :id="id" :onSuccess="addElement"/> </td> </template> <script type="text/javascript"> export default { props: { id: {type: String, required: true}, onAdded: {type: Function, required: true}, elements: {type: Object, default: function() { return {}; }} }, methods: { addElement: function(id, name, params) { this.onAdded(id, name); } } } </script> 

This code only works for the first time. First, the grid print a complete list of elements. First empty is displayed, after the first addition, the element appears. Anything added later does not fit into the array.

That is, the code: console.log ('In the cell', cellId, 'you need to add the element', name); from the grid is always executed correctly, but elements are not redrawn on the page. Tell me how to make vue to redraw all the elements, or maybe you need not to use $ set (...), but something else? already broke my head. Thanks in advance

  • By the way, when adding the second element, watch also does not work for the elements - Alexey Lapin
  • Yes, there is such a problem: 1) if the object does not have properties, they are not bandaged, if you want to get lushe, try to bind this.$set(this.elements,'field','value') one one by one there. e. Inside is this.$set(this.elements.field,'childField','value1') - Orange_shadow

1 answer 1

It turns out that the whole problem was in the object instance. When you assign a "duplicate" object to the same object, it does not work. Track. the code will not work:

 let a = this.b; a.key = 'new_value'; this.$set(this.b, a); 

The parameter b will not change anyway. Instead, you need to create a new object (clone the current one):

 let a = {}; // Здесь запускаем for и восстанавливаем экземпляр this.b в переменной aakey = 'new_value'; this.$set(this.b, a); 

The second example will work as it should