I'm building a faceted search system in VueJS. The general idea is simple:
A FilterGroup
component contains the overall filter logic. This component accepts a variety of child components, e.g. AttributeXYZFilter
. These child components are responsible for providing conditions which FilterGroup
will use to filter a collection of items.
An example usage of this system looks like this:
<template>
<FilterGroup :items="items">
<ABCFilter/>
<XYZFilter/>
<AnotherFilter/>
</FilterGroup>
</template>
My problem is as follows:
The filter components should be rendered by FilterGroup
in a specific layout. Also, FilterGroup
should provide the filter components with some additional data using props.
To avoid unnecessary coupling, FilterGroup
should not know which filters will be rendered. Each filter adheres to a common specification/interface (implemented using mixins). Each filter has its own UI template.
How can this be implemented?
I tried using slots, but I can't figure out how to custom render the child components. If no slot is being used, this.$children
is empty so I don't know which filters to render.
I could provide the filters like this:
<template>
<FilterGroup :items="items" :filters="['ABCFilter', 'XYZFilter']/>
</template>
Then FilterGroup
could dynamically import and render the filter components. It would even be possible to pass additional data. However, I think the resulting API is less readable and developer-friendly.
Is there a better way?
I think you would like to use Dynamic Components for that. This allows you dynamically render a (child) component based on the data. In your example the filters.
The :is="ComponentName"
defines the component that should be rendered. Use a props
to pass down the data:
<template>
<div class="app-body row">
<template v-for="(child, index) in children">
<component :is="child.viewName" :key="child.name" :data="child.data"></component>
</template>
</div>
</template>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With