I am trying to find a solution for overwriting the primevue component class p-accordion-header
to have different styles depending on the status of the rendered component that I can get with the variantNumber
.
This is what my code looks like:
<Accordion :multiple="true">
<AccordionTab
v-for="variantNumber in variants?.keys()"
:key="'V' + variantNumber"
>
</AccordionTab>
</Accordion>
where variants
is a simple list.
Imagine I have a function that returns the current class name called getCurrentVariantClass(variantNumber)
.
AccordionTab
because it would be a non-props attribute.div
or a simple html tag around the AccordionTab
and add a class there but the component won't render.How am I supposed to overwrite the styles of p-accordion-header
conditionally?
To be able to customize AccordionTab
to receive a variant
prop, we could create a new component that uses the extends
option, and add the prop there:
<!-- MyAccordionTab.vue -->
<script>
import { defineComponent } from 'vue'
import AccordionTab from 'primevue/accordiontab'
export default defineComponent({
name: 'AccordionTab', // must be named "AccordionTab" for Accordion to detect it
extends: AccordionTab,
props: {
variant: Number, 👈
},
render: AccordionTab.render,
})
</script>
Using the same technique above, extend the Accordion
component to override its getTabHeadherClass()
method that conditionally adds a class based on the given tab
's variant
prop:
<!-- MyAccordion.vue -->
<script>
import { defineComponent } from 'vue'
import Accordion from 'primevue/accordion'
export default defineComponent({
extends: Accordion,
methods: {
getTabHeaderClass(tab, i) {
const headerClasses = Accordion.methods.getTabHeaderClass.call(this, tab, i)
const variantClass = this.getCurrentVariantClass(tab.props.variant)
return headerClasses.concat(variantClass)
},
getCurrentVariantClass(variantNumber) {
switch (variantNumber) {
case 1:
return 'p-accordion-header-variant-a'
case 2:
return 'p-accordion-header-variant-b'
case 3:
return 'p-accordion-header-variant-c'
}
},
},
render: Accordion.render,
})
</script>
<style scoped>
.p-accordion-header-variant-a .p-accordion-header-link {
border: solid 1px red;
}
.p-accordion-header-variant-b .p-accordion-header-link {
border: solid 1px green;
}
.p-accordion-header-variant-c .p-accordion-header-link {
border: solid 1px blue;
}
</style>
Finally, use those new components in your app:
<!-- App.vue -->
<script setup>
import Accordion from '@/components/MyAccordion.vue'
import AccordionTab from '@/components/MyAccordionTab.vue'
const tabs = [/*...*/]
</script>
<template>
<Accordion multiple>
<AccordionTab v-for="tab in tabs" :key="tab.title" :variant="tab.variant" :header="tab.title">
<p>{{ tab.content }}</p>
</AccordionTab>
</Accordion>
</template>