Vue js, controlling the child component renders from parent component or synch the data of parent component's data to child components data?

Viewed 316

I am currently using Vuejs to create mandalart chart and basically the center table's data should synch with each other table's center data as shown below:enter image description here

Currently using a parent component that renders each of the 9 tables, then the table each calls one grid, common component called Item to view the data.

Parent Component

<template>
    <div>
        <h1>Mandal-art</h1>
        <div class="container">
            <div v-for="(eachArr,index) in this.getMandalObject" :key="'arr'+index">
            <!-- <div v-for="(eachArr,index) in Mandals" :key="'arr'+index"> -->
                <!-- {{this.data.mandalObject[parseInt(key)]}}dd -->
                <single-mandal
                    v-on:onChange="mandalChange"
                    :propsArray="eachArr"
                    :propsIndex="index"
                    :key="index"

                ></single-mandal>
            </div>
            <button @click="onClick('pdf')">pdf</button>
            <button @click="onClick('svg')">svg</button>

        </div>

    </div>
  
</template>

<script>
import SingleMandal from '@/components/SingleMandal';
import {mapGetters} from 'vuex';
// import {store} from '../store/index';
export default {
    name: 'MandalArt',
    data(){
        return{
            mandalObject:{
                0: [false,['first post','','','','','','','','']],
               1:[false,['second post','','','','','','','','']],
               2:[false,['third post','','','','','','','','']],
               3:[false,['fourth post','','','','','','','','']],
               4:[true,['fifth post','','','','','','','','']],
               5:[false,['6th post','','','','','','','','']],
               6:[false,['7th post','','','','','','','','']],
               7:[false,['8th post','','','','','','','','']],
               8:[false,['9th post','','','','','','','','']]
            }
        }
    },
    methods:{
        updateData: async function(index){
            console.log('before nex tick data', this.mandalObject[index][1])
            await this.$nextTick();
            console.log('after next tick data', this.mandalObject[index][1])
        },
        onClick: function(typeClick){
            if(typeClick==='pdf'){
                console.log('pdf clicked')
            }else if(typeClick==='svg'){
                console.log('svg clicked')
            }else{
                console.log('excel clickeddd')
            }
        },
        mandalChange(index, secondIndex,value){
            //this functino should connect center to medium mandal Object
            if (secondIndex===4){
                console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!')
                // this.mandalObject[index][secondIndex] = value;
                this.mandalObject[4][1][index] = value;
                //updating the center Mandal
                // this.$set(this.mandalObject[4][1], index, value)
                this.updateData(4)
            }else if(index==="4"){
                console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!@@@')
                //here enable the other mandals
                this.mandalObject[secondIndex][0] = true;
                //when changing to true, should be enabled
                this.mandalObject[secondIndex][1][4] = value;
                //updating the other mandals
                // this.$set(this.mandalObject[secondIndex][1], 4, value)
                this.updateData(secondIndex)

            }
            

            // this.$forceUpdate();
        }
    },
    components:{
        SingleMandal
    },

SingleTable Component

<template>
  <div>
      <div class="grid-container">
          <Item 
            v-on:onChange="onChild" 
            v-for="(item,index) in this.SingleMandal" 
            :key="item+index" 
            :props-boolean="Abled"
            :props-data="[index, item]"
          ></Item>
      </div>
  </div>
</template>

<script>
//need to import two components for list and listitem
import Item from '../components/common/Item';

export default {
    name:"SingleMandal",
    props: ['propsArray', 'propsIndex'],
    components:{
        Item
    },
    data(){
        return {
            SingleMandal: this.propsArray[1],
            Abled: this.propsArray[0]
        }
    },

Item Component

<template>
  <div class="item">
      <input 
        class="item-input" 
        type="text"
        v-model="inputData" 
        @input="onChangeChild" 
        :disabled="!activated"
      />
  </div>
</template>

<script>
export default {
    props: ['propsData', 'propsBoolean'],
    data() {
        return{
            inputData: this.propsData[1],
            index: this.propsData[0],
            activated: this.propsBoolean
        }
    },

    methods:{
        onChangeChild(event){
            event.preventDefault()
            this.$emit('onChange', this.index,this.inputData)
        }
    },

The Problem enter image description here

As shown above, it will not automatically update them.

** Things I did ** so I figured changing the key of the child component automatically activates re-renders on them. However, when I do that, the input loses focus after one character(obviously due to the re-render) Therefore, I wanted to control when to re-render or not losing the focus of the input after re-rendering.

Any solutions to this?

1 Answers

Use blur event and when input's blur event is called, update the key of the child element.

<input @blur="handleBlur">

...

new Vue({
  el: '#app',
  methods: {
    handleBlur(e) {
      console.log('blur')
    }
  }
})
Related