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

Problem with hide fallback slot #2878

Closed
chenyulun opened this issue Apr 9, 2021 · 6 comments
Closed

Problem with hide fallback slot #2878

chenyulun opened this issue Apr 9, 2021 · 6 comments
Labels
Resolution: Refine This PR is marked for Jira refinement. We're not working on it - we're talking it through. slot-related

Comments

@chenyulun
Copy link

Stencil version:

 @stencil/core@2.5.2

I'm submitting a:

[x] bug report
[ ] feature request
[ ] support request => Please do not submit support requests here, use one of these channels: https://stencil-worldwide.herokuapp.com/ or https://forum.ionicframework.com/

Current behavior:

Fallback slot messes between parent and child components

Expected behavior:

Correctly handle fallbak slot issues for parent and child components

Steps to reproduce:

// my-component
import { Component, h } from '@stencil/core';

@Component({
  tag: 'my-component',
  styleUrl: 'my-component.css',
  shadow: false,
})
export class MyComponent {

  render() {
    return <div><slot><span>my-component fallback</span></slot></div>;
  }
}
// my-button
import { Component, h } from '@stencil/core';

@Component({
  tag: 'my-button',
  styleUrl: 'my-button.css',
  shadow: false,
})
export class MyButton {

  render() {
    return <div>
      <my-component>
        <div data-txt="Insert into the default slot of my-component">
          <slot data-tip="lun-button The default slot of the lun-button"><span>LunButton fallback</span></slot>
        </div>
      </my-component>
    </div>;
  }
}
<!DOCTYPE html>
<html dir="ltr" lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0" />
    <title>Stencil Component Starter</title>

    <script type="module" src="/build/lun-button.esm.js"></script>
    <script nomodule src="/build/lun-button.js"></script>
  </head>
  <body>
    <!-- <my-component first="Stencil" last="'Don't call me a framework' JS"></my-component> -->
    <my-button></my-button>
  </body>
</html>
The result of the actual rendering,The page is blank
```html
my-component fallback
LunButton fallback
``` The actual rendering hides the parent component's slot fallback as well

Snipaste_2021-04-09_11-11-47

Other information:

  1. I think there should be a boundary between the elements of the parent component and the elements of the child component, and should not be mixed
  2. In fact, the problem of slot passthrough cannot be handled correctly
<div><slot name"abc" slot="abc"></slot></div>
@ionitron-bot ionitron-bot bot added the triage label Apr 9, 2021
@chenyulun
Copy link
Author

@adamdbradley @WickyNilliams
Request help to analyze, quite anxious
tks!

@chenyulun
Copy link
Author

chenyulun commented Apr 9, 2021

fix advice:

  for (i = 0, ilen = childNodes.length; i < ilen; i++) {
    childNode = childNodes[i];
    if (childNode.nodeType === NODE_TYPE.ElementNode) {
      if (childNode['s-sr']) {
        // this is a slot fallback node

        // get the slot name for this slot reference node
        slotNameAttr = childNode['s-sn'];

        // by default always show a fallback slot node
        // then hide it if there are other slots in the light dom
        childNode.hidden = false;

        for (j = 0; j < ilen; j++) {
          nodeType = childNodes[j].nodeType;

          if (childNodes[j]['s-hn'] !== childNode['s-hn'] || slotNameAttr !== '') {
            // this sibling node is from a different component OR is a named fallback slot node
            if (nodeType === NODE_TYPE.ElementNode && slotNameAttr === childNodes[j].getAttribute('slot')) {
              childNode.hidden = true;
              break;
            }
          } else {
            // this is a default fallback slot node
            // any element or text node (with content)
            // should hide the default fallback slot node
            if (
              nodeType === NODE_TYPE.ElementNode ||
              (nodeType === NODE_TYPE.TextNode && childNodes[j].textContent.trim() !== '')
            ) {
              childNode.hidden = true;
              break;
            }
          }
        }
      }

      // keep drilling down
      updateFallbackSlotVisibility(childNode);
    }
  }

Add Slots the Light DOM Judgment:!childNode['s-ol']

  for (i = 0, ilen = childNodes.length; i < ilen; i++) {
    childNode = childNodes[i];
    // no update slots in the light dom
    if (childNode.nodeType === NODE_TYPE.ElementNode && !childNode['s-ol']) {
      if (childNode['s-sr']) {
        // this is a slot fallback node

        // get the slot name for this slot reference node
        slotNameAttr = childNode['s-sn'];

        // by default always show a fallback slot node
        // then hide it if there are other slots in the light dom
        childNode.hidden = false;

        for (j = 0; j < ilen; j++) {
          nodeType = childNodes[j].nodeType;

          if (childNodes[j]['s-hn'] !== childNode['s-hn'] || slotNameAttr !== '') {
            // this sibling node is from a different component OR is a named fallback slot node
            if (nodeType === NODE_TYPE.ElementNode && slotNameAttr === childNodes[j].getAttribute('slot')) {
              childNode.hidden = true;
              break;
            }
          } else {
            // this is a default fallback slot node
            // any element or text node (with content)
            // should hide the default fallback slot node
            if (
              nodeType === NODE_TYPE.ElementNode ||
              (nodeType === NODE_TYPE.TextNode && childNodes[j].textContent.trim() !== '')
            ) {
              childNode.hidden = true;
              break;
            }
          }
        }
      }

      // keep drilling down
      updateFallbackSlotVisibility(childNode);
    }
  }

@chenyulun
Copy link
Author

Hidden slot and hidden slot fallback should be processed centrally and not separately.
Initialization should hide all slots,
When checking for slot in a Web component, move the external slot into the component, unhide the slot, and set the slot fallback to hidden.

@chenyulun
Copy link
Author

When a Web component initializes the hidden slot tag, the component records $flags$of 4 because the external slot elements are processed only when the internal check reaches the slot tag, so the external slot elements are not hidden

@nicolas-skrzek
Copy link

Is the problem solved? I see there is a PR that contains a fix for this issue. But I'm in @stencil/core@2.7.0 and I've this issue.

@rwaskiewicz rwaskiewicz added slot-related Resolution: Refine This PR is marked for Jira refinement. We're not working on it - we're talking it through. and removed Resolution: Needs Investigation This PR or Issue should be investigated from the Stencil team labels Sep 6, 2023
@tanner-reits
Copy link
Member

This doesn't appear to be an issue in the latest version of Stencil (v4.9.1 at the time of this comment). Please let us know if you encounter this issue on the latest or future version(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: Refine This PR is marked for Jira refinement. We're not working on it - we're talking it through. slot-related
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants