Skip to content
Advertisement

Component inside Component – VueJS

I am having a hard time to understand this, so I have a component which is already complied which is a grid, now when I click on a button a modal pops-up and display another grid inside the modal at this point my code looks like this for the modal pop-up

<template>

    <transition v-if="this.modalVisible" v-bind:title.sync="this.modalVisible" name="modal">
        <div class="modal-mask">
            <div class="modal-wrapper">
                <div class="modal-container">

                    <div class="modal-header">
                        {{ modalHeaderName }}
                    </div>

                    <div class="modal-body">
                     //this is another component
                    <grid-data :grid-values="dummy" :tool-bar="false"></grid-data> 
                    </div>

                    <div class="modal-footer">

                    </div>
                </div>
            </div>
        </div>
    </transition>

</template>

<script>
    import DataTable from './core/gridTable.vue';


    export default {
        components:{
            JqxButton,
            'grid-data' : DataTable,
        },
        props : {
            modalHeaderName : String,
            modalVisible : Boolean
        },
        data: function () {
            return {
                buttonWidth: 120,
                buttonHeight: '100%',
                value: this.buttonName,
                dummy : [
                    { name: 'ProductName', type: 'string' },
                    { name: 'QuantityPerUnit', type: 'int' },
                    { name: 'UnitPrice', type: 'float' },
                    { name: 'UnitsInStock', type: 'float' },
                    { name: 'Discontinued', type: 'bool' }
                ],
            }
        }
    }
</script>

Now, the grid is a vue component which was already complied and rendered, now will I import it again it says

[Vue warn]: Failed to mount component: template or render function not defined.

<template>
    <div>
        <!-- sync here is, getting the value from the updated modal-->
        <custom-modal :modal-visible="this.showModal"  v-bind:showModal.sync="showModal" :modal-header-name="this.modalHeaderName"></custom-modal>
        <JqxGrid :width="width" :source="dataAdapter" :columns="gridValues"
                 :pageable="true" :autoheight="true" :sortable="true"
                 :altrows="true" :enabletooltip="true" :editable="true"
                 :selectionmode="'multiplecellsadvanced'"  :showtoolbar="this.toolBar" :rendertoolbar="rendertoolbar">
        </JqxGrid>
    </div>

</template>
<script>
    import JqxGrid from "../jqx-vue/vue_jqxgrid.vue";
    import CustomModal from "../customModal";
    export default {
        components: {
            JqxGrid,
            'custom-modal' : CustomModal
        },
        // added the name here
        name: 'jqx-grid',
        props : {
            gridValues : Array,
            toolBar : Boolean
        },
        data: function () {
            return {
                showModal : false,
                modalHeaderName : '',
                width: '100%',
                dataAdapter: new jqx.dataAdapter({
                     datatype: 'xml',
                     datafields : this.gridValues,
                     url: ''
                }),
                columns: []
            }
        },
        mounted: function () {
            this.createButtons();
        },
        methods: {
            rendertoolbar: function (toolbar) {
                let buttonsContainer = document.createElement('div');
                buttonsContainer.style.cssText = 'overflow: hidden; position: relative; margin: 5px;';

                let addButtonContainer = document.createElement('div');
                let deleteButtonContainer = document.createElement('div');

                addButtonContainer.id = 'addButton';
                deleteButtonContainer.id = 'deleteButton';

                addButtonContainer.style.cssText = 'float: left; margin-left: 5px;padding-bottom:25px;';
                deleteButtonContainer.style.cssText = 'float: left; margin-left: 5px;padding-bottom:25px;';

                buttonsContainer.appendChild(addButtonContainer);
                buttonsContainer.appendChild(deleteButtonContainer);
                toolbar[0].appendChild(buttonsContainer);
            },
            createButtons: function () {

                let addButtonOptions = {
                    height: 25, value: '&nbsp; <i class="fa fa-plus" style="padding-top:3px"></i> &nbsp;Add Items &nbsp;',
                };
                let addButton = jqwidgets.createInstance('#addButton', 'jqxButton', addButtonOptions);
                let deleteButtonOptions = {
                    height: 25, value: '&nbsp; <i class="fa fa-ban" style="padding-top:3px"></i> &nbsp;Remove All &nbsp;',
                };
                let deleteButton = jqwidgets.createInstance('#deleteButton', 'jqxButton', deleteButtonOptions);

                // add new row.
                addButton.addEventHandler('click', (event) => {
                    this.showModal = true;
                    this.modalHeaderName = 'Bulk Add Items';
                });
                // delete selected row.
                deleteButton.addEventHandler('click', (event) => {
                   // alert('delete')
                });

            },
            cellsrenderer: function (row, columnsfield, value, defaulthtml, columnproperties, rowdata) {
                if (value < 20) {
                    return '<span style="margin: 4px; float: ' + columnproperties.cellsalign + '; color: #ff0000;">' + value + '</span>';
                }
                else {
                    return '<span style="margin: 4px; float: ' + columnproperties.cellsalign + '; color: #008000;">' + value + '</span>';
                }
            }
        }
    }
</script>

How can I overcome this issue?

I have seen question like this which says the component grid is trying to compile again and hence the error but I am not sure of that, so we should be using the complied version of the grid component.

NOTE: Using Vue with Laravel 5.4

Error Image enter image description here

Advertisement

Answer

I didn’t see an obvious error when you first posted the code. Right now I see JqxButton inside components of the upper code block, which would be undefined. In your code, you always import some components for which we can’t see the code.

Generally, when I’m in a situation like this and everything seems to be looking okay, I remove all sub-components and see if the error goes away. Then, I re-add one component after each other until I hit the error again and try to debug it there.

From your description, I suspect you have some kind of cycle in your dependencies and you might find the documentation about circular references helpful.

Vue needs a lazy import for circular dependencies:

components: {
  "my-circular-dependency": () => import("./my-circular-dependency.vue");
}
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement