简体   繁体   中英

Use a component to render each Vuetify expansion panel item

I'm trying to using Vuetify's v-expansion-panel component (AKA accordion) to render one panel for each task in a list. The parent component's template is:

<div v-if="tasks.length">
  <v-expansion-panels>
    <task
      v-for="(task, index) in tasks"
      :task="task"
      :key="index"
    />
  </v-expansion-panels>
</div>

Then the child task component renders the content of each panel like so:

<template>
  <v-expansion-panel>

    <v-expansion-panel-header>
    <!-- render panel header content -->
    </v-expansion-panel-header>

    <v-expansion-panel-content>
    <!-- render panel body content -->
    </v-expansion-panel-content>

  </v-expansion-panel>
</template>

It's convenient for me to render the header and body in a single component, because they largely depend on the same data. However, I don't like the way that the markup for the expansion panels is split over two different components. Because of this, if I unit test the child task component I get a warning:

[Vuetify] The v-expansion-panel component must be used inside a v-expansion-panels

Is there a way I can move all the expansion panel markup into the parent component, but generate the content for v-expansion-panel-header and v-expansion-panel-content in the child task component?

Why not just add all expansion panels together and in task.vue do the v-for?

<task :tasks="tasks" />

Task.vue

 <template>
    <v-expansion-panels 
      <v-expansion-panel
         v-for="(task, index) in tasks"
         :task="task"
         :key="index">>
    
        <v-expansion-panel-header>
        <!-- render panel header content -->
        </v-expansion-panel-header>
    
        <v-expansion-panel-content>
        <!-- render panel body content -->
        </v-expansion-panel-content>
    
      </v-expansion-panel>
    </v-expansion-panels>
    </template>

You can have multiple root elements in Vue 2 using render functions. It is more tricky to use but it would work. Take a look at this link .

Alternatively, you can use the vue-fragment component (link to npm page ) that does it for you like so:

<template>
  <fragment>
    <v-expansion-panel-header>
    <!-- render panel header content -->
    </v-expansion-panel-header>

    <v-expansion-panel-content>
    <!-- render panel body content -->
    </v-expansion-panel-content>
  </fragment>
</template>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM