0

I want to create a Grid component that accepts the number of columns from the user, accepts data and renders all it's children into consecutive cells.

Something like this.

<Grid :cells="12" :columns="6">
    <div>Child1 Cell1</div>
    <div>Child2 Cell2</div>
    <div>Child3 Cell3</div>
    <div>Child4 Cell4</div>
    <div>Child5 Cell5</div>
    <div>Child6 Cell6</div>
</Grid>

In the Grid.vue component in the template, this is what I expect to do.

<div class="nugget-grid-item" v-for="cell of cells" :key="cell">
    {cell}
</div>

This will render something like this on the UI. Grids

The dashed border on each cell is due to the nugget-grid-item CSS class, but CSS is not relevant here, so let's ignore that.

What I am not able to figure out is how do I get this Grid component to display the following. enter image description here

Isn't there something like this.children from React in Vue?

1 Answer 1

2

What you need are slots. See docs here. As you'll see slots allow a parent component to pass DOM elements into a child component. A basic look at them could go like this:

//ChildComponent.vue
<template>
  <div>
    <p>I'm the child component!</p>
    <!-- Content from the parent gets rendered here. -->
    <slot></slot>
  </div>
</template>

And then you inject content into the slot tags like this:

//ParentComponent.vue
<template>
  <div>
    <child-component>
      <p>I'm injected content from the parent!</p>
      <p>I can still bind to data in the parent's scope, like this! {{myVariable}}</p>
    </child-component>
  </div>
</template>

Slots can get pretty complex and do a lot of things so are well worth looking into.

Further to your below comment, you can put a v-for in the grid. This outputs what you seem to be after. I've put an input in to accept the users number of columns as you said and it then renders that number of cells. You can of course use multiple slots and named slots and scoped slots but I'll leave it up to you how you expand on this.

//Grid.vue
<template>
    <div class="cell">
        <slot></slot>
    </div>
</template>

<script>
export default {
    
}
</script>
 <style scoped>
    .cell {
        height: 40px;
        width: 60px;
        border: 1px solid gray;
    }
 </style>

and parent:

<template>
    <div class="content">
        
        <label>Enter number of columns</label>
        <input v-model.number="col" type="number">
        <Grid v-for="(n, i) in col" :key="i" >
            <div>Child{{n}} Cell{{n}}</div>
        </Grid>
    </div>
</template>

<script>

import Grid from '@/components/admin/Grid'

export default {
    layout: 'admin',
    components: {
        Grid
    },
    data: () => ({
        
        col: 4
    }),
}
</script>
Sign up to request clarification or add additional context in comments.

2 Comments

I tried slot, but my guess it can be used only once. What if I do a v-for inside of the Grid component? Something like <Grid :cells="12" :columns="6"><div v-for="item in data">{{ item }}</div></Grid>
Thanks Andrew. I actually used your suggestion/solution and used it to implement a Grid that I was expecting to render. I will get back again once I have that completed and then mark your solution as the answer with some things I had modified!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.