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

Rendering a Single Node in a Portal #20

Open
johndugan opened this issue Jul 16, 2019 · 12 comments
Open

Rendering a Single Node in a Portal #20

johndugan opened this issue Jul 16, 2019 · 12 comments

Comments

@johndugan
Copy link
Contributor

Hi Linus,

I'm not sure if this is a bug. I'm new to Vue, so bare with me. I am using simple portal as a local component, and passing it a single child component, like below.

<Portal selector="#site-footer">
    <AppStatusbar
        document-type="order"
        :pending-count="pendingCount"
        :is-sending="false"
        :is-success="false"
        :is-error="false"
    />
</Portal>

^ This will not render.

<Portal selector="#site-footer">
    &nbsp;
    <AppStatusbar
        document-type="order"
        :pending-count="pendingCount"
        :is-sending="false"
        :is-success="false"
        :is-error="false"
    />
</Portal>

^ This will render.

If I remove the ternary condition in your render function as shown below, my first example renders.

render: function render(h) {
    var nodes = this.updatedNodes && this.updatedNodes();
    if (!nodes) return h();
    // return nodes.length < 2 && !nodes[0].text ? nodes : h(this.tag || 'DIV', nodes);
    return h(this.tag || 'DIV', nodes);
}

So, wondering what the purpose of the ternary check is?

Thanks!

@Paul-Hebert
Copy link

Hmm, I'm running into the same issue. I added <span></span> instead of &nbsp; to fix it but this still feels like a hack.

It looks like the ternary is determining whether it needs to wrap the content in an element or not? I'm not sure why it fails when you return nodes but I just end up with a comment in my code (<!---->)

mpbarlow added a commit to mpbarlow/vue-simple-portal that referenced this issue Oct 22, 2019
Not too sure why this works, or rather, why it doesn’t work without this rather strange approach.

Unless I’m mistaken, the correct return value when `nodes.length < 2 && !nodes[0].text` is true should be `nodes[0]` rather than just `nodes` (as `nodes` is an array, not a VNode).

However, returning just `nodes[0]` does not fix the bug where the portal contents don’t render as described in LinusBorg#20. Calling `createElement` on its constituent parts works, despite the output of the function and the initial `nodes[0]` VNode appearing identical upon inspection.
@mpbarlow mpbarlow mentioned this issue Oct 22, 2019
@ingebretsen
Copy link

ingebretsen commented Nov 22, 2019

I'm hitting this as well. The &nbsp; hack works for now but feels wrong.

@alexmiddeleer
Copy link

I don't want to create annoying noise because I really appreciate this library, but I think this bug is serious and deserves an expedited fix. As I was trying to build out a proof of concept it was very confusing and frustrating. Even though the extra span is totally insignificant, it makes the library seem unpolished and not production-ready.

@LinusBorg
Copy link
Owner

LinusBorg commented Mar 7, 2020

Hi. So first of all apologies that this totally went under my radar for some reason.

I now tried to reproduce this but failed.

In unit tests as well as the demo app that I run in this Project, I can portal content with a single element as content just fine.

I think I remember that in previous version of Vue, rendering actually failed when you returned an array of Vnodes whereas now it just picks the first element from the array and is fine with it - but I'm not sure.

So: What version of Vue do you actually have in your project's lock files?

Anyway, returning a single node here instead of thew array should fix this for you:

I'll get on it / get on #33

@alexmiddeleer
Copy link

Confirmed it not being reproducible in the simplest case. https://codesandbox.io/s/determined-bartik-hueqe. I will try to find versions that fail, and others can use this codesandbox for the same purpose.

@alexmiddeleer
Copy link

alexmiddeleer commented Mar 7, 2020

My version of Vue is 2.6.11 and simple portal is 0.1.4 (based on lockfile). Even with these versions locked I still can't get the codesandbox to show the bug (https://codesandbox.io/s/snowy-fast-sc084). Technically we're using the esm version of vue (our webpack has this resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js' } } but I tried and failed to wire together something with the browser esm version of Vue, in codesandbox. It's possible something in our build process (babel etc) is causing a fallback to a legacy behavior in Vue, but I'm currently out of ideas for tracking it down and it may not be worth a wild goose chase.

@Paul-Hebert
Copy link

Hey! My project is currently using Vue 2.6.10, though I'm not sure whether that was the version I was using when I ran into this bug.

@cbommart
Copy link

cbommart commented Jul 27, 2020

Still got the issue ...

My component :

<template>
  <Portal>
    <div>
        Component content
    </div>
  </Portal>
</template>

<script>
import { Portal } from '@linusborg/vue-simple-portal';
export default {
  name: 'MyComponent',
  components: {
    Portal,
  },
};
</script>

This doesn't work :

<Portal>
   <div>
       Component content
   </div>
</Portal>

But this work :

<Portal>
   <span></span>
   <div>
       Component content
   </div>
</Portal>

Thank you for the package ! But this "bug" is a bit annoying 😄

Edit :
My VueCli version : @vue/cli 4.4.6
My node version : v12.16.2
My npm version : 6.14.4

@hermanndettmann
Copy link

I also ran into this issue. Any updates on that @LinusBorg ?

@LinusBorg
Copy link
Owner

LinusBorg commented Aug 13, 2020

@hermanndettmann As I explained in my previous comment, I so far failed to reproduce this problem, and non one was able to provide an actual, runnable reproduction or at least tell me the versions of Vue and this package itself that this fails with.

So unfortunately there are no updates on this, no.

@joergd
Copy link

joergd commented Aug 25, 2020

I have the same issue.

My portal version is: 0.1.4
Vuejs: 2.6.12

I am using it like in this sandbox (which unfortunately works as intended):
https://codesandbox.io/s/trusting-bartik-cb3ee?file=/index.html

Though - the only different is I use the npm versions, and import the Portal wherever I need it

import { Portal } from "@linusborg/vue-simple-portal"

But not sure how to setup this scenario on codesandbox ...

So - I don't know if this would impact it in any way - but other than that I can't think of any differences between the sandbox and my code.

@susnux
Copy link

susnux commented Jan 11, 2024

Same problem with vue-simple-portal 0.1.5 and vue 2.7.14.

It seems to be related to this line, because if I remove it and replace it with always h(this.tag, nodes) it works.

return nodes.length < 2 && !nodes[0].text ? nodes : h(this.tag, nodes)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants