javascriptvuejs2vue-componentvue-dynamic-components

vue dynamic components, repeat info


I have a list that, if you click to open it and list the children, you make a request ajax to load the data and paint a sub list, the component that performs this work is the same, is recursive and is loaded on the children through dynamic components, the problem is that when you load the children of the second list. and opens a third these are repeated.

tree picture

import * from '....';

export default {
    name: 'cList',
    components : {
        itett,
    },
    props : ['id', 'entity', 'treeData'],
    data  : ()=>{return{
        loading: true,
        tree: {},
        child_component: false,
        tdata: false,
    }},
    methods: {
        clop: function(state, uid, ev){
            let _childs = document.querySelector(`[data-idml="${uid}"]`);
            if( _childs ) {
                switch (state) {
                    case 'close': _childs.classList.add('hide'); break;
                    case 'open' : _childs.classList.remove('hide'); this.getChildren(uid); break;
                }
            }
        },
        getChildren: function( uid ){
            this.child_component = false;
            let _tdata = {};
            let de   = uid.split('_');
            let _elm = Entity.create({ is: de[0], id: de[1] });
            let tot  = _elm.childs.length - 1, cnt = 0;

            _elm.childs.forEach((et, ix) => {
                if( _elm.type && _elm.id ) {
                    ApiEntity.getList({
                        entity: et,
                        parents: [+_elm.id],
                        parentType: _elm.type,
                        cascade: false,
                    }).then(res => {
                        if( Array.isArray(res) ) {
                            _tdata[et] = res;
                        }
                        if( cnt >= tot ) {
                            this.tdata = _tdata;
                            this.child_component = 'cList';
                        }
                        cnt++;
                    }).catch( err => { console.error( err ); });
                }
            });
        },

        seeMore: function(uid){ }

    },
    beforeMount: function(){
        this.tree = {};
        if( this.entity ) {
            Entity.fetch(this.entity)
            .then(res => {
                this.tree[this.entity] = res;
                this.loading = false;
            }).catch( err => { console.error( err ); });

        } else if( this.treeData ) {
            this.tree = this.treeData;
            this.loading = false;
        }
    },

}
<div class="ch_list">
    <template v-if="loading"> Loading.... </template>
    <template v-else>
    <ul class="lsitm" v-for="(value, name, ig) in tree" :key="ig">
        <li v-for="(elm) in value" :key="elm.uid">
            <itett class="ls_line" :data="elm" @clop="clop"></itett>
            <div class="ls_childs hide" :data-idml="elm.uid">
                <div class="ch_header"></div>
                <!-- <keep-alive> -->
                    <component v-bind:is="child_component" :treeData="tdata"></component>
                <!-- </keep-alive> -->
                <div class="ch_more"> <button @click="seeMore(`${entity}_${id}`, $event)">see mas</button> </div>
            </div>
        </li>
    </ul>
    </template>
 </div>

something like this https://codepen.io/anthonygore/pen/PJKNqa?editors=1010, but each item is a call to an api


Solution

  • look at this example, the data is in the folder public/data

    https://codesandbox.io/s/vue-template-ntkmh?fontsize=14

    Edit Vue Template