Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slots resolving issue on subsequent components #7710

Comments

@miljan-aleksic
Copy link

Version

2.5.13

Reproduction link

https://codesandbox.io/s/316wjk4w41

Steps to reproduce

As stated by the docs slots() in fn components should be used only when the component knows about them, otherwise should pass along the children and the next component could deal with them.

What is expected?

I would expect that all children component would resolve slots correctly as long as children are passed along.

What is actually happening?

Only the initial component gets resolved the slots well, while any subsequent component that gets the children passed along doesn't.

@posva
Copy link
Member

posva commented Feb 27, 2018

When passing down children, you have to specify where to place them although I would agree it would make things easier if they were assigned automatically to their corresponding but think about it when writing a template. This is the way you would do it

// ComponentA.vue
<CompB>
  <slot name="foo" slot="foo"/>
</CompB>

Note how you have to explicitly name the slot and say it is a slot of CompB

You need to do the same things with render functions, here is an example doing it in functional and non-functional components https://jsfiddle.net/posva/fseLahxu/

@yyx990803 I'm not sure if I'm giving the right solution. If it is, I think I should do a PR to document this, although I'm not sure what approach to take cc @chrisvfritz
The documentation only shows off the slot attribute but doesn't have any section about how to pass slots in render functions

@chrisvfritz
Copy link
Contributor

@posva I think the difference is templates don't have a concept of just children, since they're not meant to be used for transparent wrappers of other components. And it's not exactly a "transparent" wrapper if it has to know about the slots of the child in order to explicitly pass them. So this does sound like a bug to me.

@miljan-aleksic
Copy link
Author

Thank you @yyx990803 :)

yyx990803 added a commit that referenced this issue Mar 13, 2018
Named slots should be respecred when passing raw children down multiple
layers of functional components.

fix #7710
@yyx990803
Copy link
Member

Heads up: we are likely going to revert this change in 2.6.

This commit has led to a regression in #7958 and after revisiting the change, I believe it is technically incorrect to support it. Passing a raw children array down should mean discarding named slots information.

For your use case (creating transparent wrappers that pass down named slots as-is), here's a work around:

// a helper that explicitly passes down the same named slots that are passed in
function mapSlots (h, slots) {
  return Object.keys(slots).map(name => {
    return h('template', { slot: name }, slots[name])
  })
}

const CompA = {
  functional: true,
  render (h, { slots }) {
    return h(CompB, mapSlots(h, slots()))
  }
}

This is obviously a more verbose workaround, but it is necessary for now to ensure correct behavior in #7958, which is a more common use case.

We should also consider an easier way to pass down named slots in render functions, pretty much like scopedSlots:

const CompA = {
  functional: true,
  render (h, { slots }) {
    return h(CompB, { slots: slots() })
  }
}

@miljan-aleksic
Copy link
Author

Ok, thanks for the warning.

f2009 pushed a commit to f2009/vue that referenced this issue Jan 25, 2019
Named slots should be respecred when passing raw children down multiple
layers of functional components.

fix vuejs#7710
aJean pushed a commit to aJean/vue that referenced this issue Aug 19, 2020
Named slots should be respecred when passing raw children down multiple
layers of functional components.

fix vuejs#7710
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment