0
votes

I am developing a Vue app with pimcore and twig in the backend. I have to create a component that receives the slot (another component), and render it inside, but with dynamic props.

Here is root in viani.twig.html:

<div>
    <viani-accordion>
        <viani-filter-checkbox v-slot="{filterRows}"></viani-filter-checkbox>
    </viani-accordion>
</div>

There is nothing special. viani-accordion is a parent component and the viani-filter-checkbox is a slot, which I have to render with appropriate props.

Here you can see the VianiAccordion.vue:

<template>
    <div class="wrapper">
        <AccordionTitle v-for="(item, index) in dataToRender" :item="item" :key="index">
            /*I think this is incorrect, but I'm trying to prop data that I need in viani-filter-checkbox*/         
            <slot :filter-rows="item.items"></slot>
        </AccordionTitle>
    </div>
</template>
<script>
    import AccordionTitle from './Accordion-Title';
    export default {
        name: "Viani-Accordion",

        components: {AccordionTitle},

        data() {
            return {
                dataToRender: [
                    {
                        name: 'first item',
                        items: [
                            {
                                name: 'oil olive',
                                quantity: 10,
                            },
                            {
                                name: 'subitem 2',
                                quantity: 11,
                            },
                        ]
                    },
                    {
                        name: 'second item',
                        items: [
                            {
                                name: 'subitem 1',
                                quantity: 10,
                            },
                            {
                                name: 'subitem 2',
                                quantity: 11,
                            },
                        ]
                    }
                ]
            }
        },
    }
</script>

Then I have another deeper child component Accordion-Title.vue that is responsible for rendering the slot (so I have to pass the slot through the multiple components):

<template>
    <div v-if="isOpen" class="child-wrapper">
        /*I think this is incorrect, but I'm trying to prop data that I need in viani-filter-checkbox*/
        <slot :filterRows="item.items"></slot>
    </div>
</template>
<script>
    export default {
        name: "Accordion-Title",
        props: {
            item: {
                type: Object,
                default: null
            }
        }
    }
</script>

and finally Viani-FiltersCheckbox.vue:

<template>
    <div>
        //child component which we don't need in this case
        <FilterCheckboxRow v-for="(item, index) in filterRows" :item="item" :key="index"/>
    </div>
</template>

<script>
    import FilterCheckboxRow from './FilterCheckboxRow'
    export default {
        name: "VianiFilterCheckbox",
        components: {
            FilterCheckboxRow
        },
        props: {
            //here I expect to get array to render, but got default value (empty array)
            filterRows: {
                type: Array,
                default: function () {
                    return []
                }
            },
        },
    }
</script>

So I need to pass the props (filterRows) to the component (Viani-FiltersCheckbox.vue), which is rendered as a slot. I have read this and this, but still don't get where the mistake and how to get the props I need.

1

1 Answers

1
votes

It looks like you're trying to access your props through props.XXX. That's typically only done in templates for functional components. Otherwise, the props would be accessed without the props. prefix (i.e., props.item.items should be item.items).

And to pass filterRows from the scope data to the child component, declare a <template>, and then move your child into that, binding filterRows there:

<viani-accordion>
    <!-- BEFORE: -->
    <!-- <viani-filter-checkbox v-slot="{filterRows}"></viani-filter-checkbox> -->

    <template v-slot="{filterRows}">
        <viani-filter-checkbox :filterRows="filterRows"></viani-filter-checkbox>
    </template>
</viani-accordion>

Edit Passing scope data to children