Faced a problem. Dynamically form the form from select on Vue.js from the list:

var inpData = [ { id: 1, pid: 0, tag: 'select', title: 'установка ПО'}, { id: 2, pid: 0, tag: 'select', title: 'обслуживание оргтехники'}, { id: 3, pid: 1, tag: 'select', title: 'стандартные ПО'}, { id: 4, pid: 1, tag: 'select', title: 'программы ИВЦ'}, { id: 5, pid: 2, tag: 'select', title: 'замена картриджа'}, { id: 6, pid: 2, tag: 'select', title: 'установка принтера'}, { id: 7, pid: 5, tag: 'input', title: 'модель картриджа'} ] 

those. the first select are objects with pid = 0, the second with pid = 1 or 2, etc. When the page is loaded, the first select is formed - this is where pid = 0. When you select the first select, let's say "software installation", everything works correctly and the second select is added to the page with pid = 1: correctly
But when changing the value in the first select to "office equipment maintenance", the second select does not change, everything that is connected with the "software installation" still hangs in it: not correct

Although when printing the array myElements in the console after push (), you can see that it is filled as it should be. Adding to the array myElements through this. $ Set does not help.

If during the formation of the array myElements add setTimeout (commented out in the code), then everything works correctly. The documentation says that push and splice are reactive. What is the reason for this behavior?

 <template> <div> <form> <transition-group name="fade"> <div v-for="(elem, index) in myElements" :key="index" class="form-group"> <template v-if="elem.tag == 'select'"> <select-component v-on:change-select="changeSelect($event)" v-bind:options="elem.data" v-bind:index="index"> </select-component> </template> <template v-else-if="elem.tag == 'input'"> <input-component></input-component> </template> </div> </transition-group> </form> </div> </template> <script> import SelectComponent from './SelectComponent' import InputComponent from './InputComponent' var inpData = [ { id: 1, pid: 0, tag: 'select', title: 'установка ПО'}, { id: 2, pid: 0, tag: 'select', title: 'обслуживание оргтехники'}, { id: 3, pid: 1, tag: 'select', title: 'стандартные ПО'}, { id: 4, pid: 1, tag: 'select', title: 'программы ИВЦ'}, { id: 5, pid: 2, tag: 'select', title: 'замена картриджа'}, { id: 6, pid: 2, tag: 'select', title: 'установка принтера'}, { id: 7, pid: 5, tag: 'input', title: 'модель картриджа'} ] function myFilter(pid) { return inpData.filter( x => x.pid === pid ) } export default { data: function() { return { myElements: [], } }, components: { 'select-component': SelectComponent, 'input-component': InputComponent }, methods: { changeSelect(data) { var val = Number(data.val), idx = Number(data.idx) this.myElements.splice(idx + 1) var tmp = myFilter(val), tag = '', pid = null if(tmp.length === 1) { tag = 'input' pid = tmp[0].pid } else if(tmp.length > 1) { tag = 'select' pid = tmp[0].pid } if(tag != '' && val !=0) { //при прогоне через setTimeout все работает //var $this = this //setTimeout(function() { this.myElements.push({ tag: tag, data: tmp }) //}, 3000) } } }, created() { this.myElements.push({ tag: 'select', data: myFilter(0) }) }, } </script> <style> .fade-enter-active, .fade-leave-active { transition: opacity .3s; } .fade-enter, .fade-leave-to /* .fade-leave-active до версии 2.1.8 */ { opacity: 0; } </style> 

UPDATE! I figured out if I removed the data () method in the SelectComponent component and directly into the cycle with pass options, then everything changes as expected, strange behavior, in my opinion, and if I want to validate, for example, the input data ?:

 <template> <select v-on:change="$emit('change-select', $event.target.value)" class="form-control"> <option value="0">выберите из списка</option> <option v-for="option in selectOptions" v-bind:value="option.id">{{ option.title }}</option> <option value="-1">другое</option> </select> </template> <script> export default { props: ['options'], /* это нужно передавать вместо selectOptions */ data() { return { selectOptions: this.options, } } } </script> 

    2 answers 2

    Looked at the code. The data is successfully transferred to the select-component , but further they are not used in any way. Those. the data is set only once, and when the input parameters are updated, nothing happens.

      data() { return { selectOptions: this.options, selectIndex: this.index } }, 

    In order to be able to use the changing data, you must either use it directly in the code, without wrapping it in selectOptions , or use tracking: watch or calculated properties .

     <option v-for="option in options" v-bind:value="option.id">{{ option.title }}</option> 

    Good luck.

      Unfortunately, the code that you gave above is difficult to check for "live", so I can only assume that the fact is that the myFilter function returns a non-reactive array, which causes the reactivity of the myElements array.

      Purely from practice, such problems are easiest to solve if you use not a method to compile a new array, but a calculated property that the array returns and which is used further. At the same time, the array will definitely be reactive and will not have to worry about this anymore.

      • Randomly deleted the previous comment. You can try live here - Denis Nesteruk
      • I Shmog), the answer added to the page. I understand your comment now. Thank! - Denis Nesteruk