redfox05
redfox05

Reputation: 3692

How do you programatically define Vue.js slot props without using the SFC template <slot :prop=some_data>?

Normally you would define slot props in the child component by using:

<template>
    <slot :myProp="some_data" />
</template>

But how can you define myProp if you are not using the <slot> syntax in the child component <template>?

In my use case, I am using a computed property to iterate across this.$slots.default() and filtering the components that are passed into the slot, then the result of this is used together with <component> to render the filtered components from the slot. This part works well.

However, what I need to figure out next is to pass props into the slot for the parent to consume. Any suggestions?

Further context

As there has already been a misunderstanding of my question, I will try to elaborate by sharing some more of the code. I fear this might complicate the question, but at least it shows how the basic slot definition solutions won't work here.

child component:

<template>
    <component
      :is="field" v-for="(field, i) of fields"
      :key="getFieldKey(field, i)">
    </component>
</template>

And the computed fields logic is:

fields() {
    return this.$slots.default?.().reduce((slot_components, child) => {
        if (this.isFormField(child)) {
            slot_components.push(child);
        } else if (child.children && child.children instanceof Array) {
            child.children.forEach((nestedChild) => {
                if (this.isFormField(nestedChild)) {
                     slot_components.push(nestedChild);
                }
            });
        }

        return slot_components;
    }, []);
}

Upvotes: 1

Views: 46

Answers (1)

Matt Smith
Matt Smith

Reputation: 2158

Modify the child component template to use v-bind to pass the props to the <component>.

Child component:

<template>
  <div>
    <component
      v-for="(field, i) in normal_fields"
      :is="field"
      :key="getFieldKey(field, i)"
      v-bind="getProps(field, i)"
    ></component>
    <template v-for="(t_field, j) in teleport_fields" :key="getFieldKey(t_field.field, j)">
      <Teleport defer :to="t_field.target_dom_element">
        <component :is="t_field.field" v-bind="getProps(t_field.field, j)"></component>
      </Teleport>
    </template>
  </div>
</template>

You'll need to update the computed property to ensure that the props are included when rendering the components.

Upvotes: 0

Related Questions