Search code examples
typescriptvue.jsprimevue

How to pass slots through from Parent to Child Components with PrimeVue?


I am trying to wrap some PrimeVue components to make my own component library. But how do I handle all the slots?

Some PrimeVue components have a large number of slots so passing each one individually would be a massive pain.

Fortunately, I found this solution to pass all slots from Parent to Child Component.

Here is an example in use with the PrimeVue Dropdown component:

<Dropdown v-bind="$attrs" >
  <template v-for="(_, name) in $slots" #[name]="scope">
    <slot :name v-bind="scope" />
  </template>
</Dropdown>

Unfortunately, it doesn't work with PrimeVue because TypeScript it gives this error on #[name] regarding no index signature on DropdownSlots:

Element implicitly has an 'any' type because expression of type 'string | number' can't be used to index type 'DropdownSlots'.

No index signature with a parameter of type 'string' was found on type 'DropdownSlots'. ts(7053)

Any ideas for a workaround?


Solution

  • That there's TypeScript error doesn't mean code is wrong. Vue templates aren't currently type-safe by design and require third-party tools (vue-tsc, IDEs) for type checking that can have their own quirks.

    It's easier to transform children and props in render function instead of a template, this also avoids the problems associated with the use of types in a template. For a simple wrapper component it is:

    setup(props, { slots }) {
      return () => h(Dropdown, props, slots);
    }