ionic-team / stencil

A toolchain for building scalable, enterprise-ready component systems on top of TypeScript and Web Component standards. Stencil components can be distributed natively to React, Angular, Vue, and traditional web developers from a single, framework-agnostic codebase.
https://stenciljs.com
Other
12.56k stars 787 forks source link

Out of order slot rendering for double-nested Slot components in polyfilled browsers #840

Closed mattdsteele closed 6 years ago

mattdsteele commented 6 years ago

Stencil version:

 @stencil/core@0.9.7

I'm submitting a:

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

Current behavior:

This one's a doozy. It appears to only happen in Angular apps, only in polyfilled browsers (Firefox, Edge, IE11, etc), and only with Stencil components that nest slots within each other. 😱

From what I can tell this began to occur with Stencil 0.8.0, which makes me think it's related to the slot refactoring work.

Here's a demo (open with Firefox or Edge): https://stackblitz.com/edit/angular-oygzm2

Stencil Code

https://github.com/mattdsteele/mattdsteele-stencil-bug-1

There's an inner component that just renders a <slot />:

export class InnerComponent {
  render() {
    return <slot />;
  }
}

And an outer component that renders <inner-component>, and passes through its slotted content:

export class OuterComponent {
  render() {
    return (
      <inner-component>
        <slot />
      </inner-component>
    );
  }
}

Both are set to shadow: true.

Angular code that consumes it

The Angular template is using the Stencil component fairly normally:

  <outer-component>
    <a href="">Link 1</a>
    <a href="">Link 2</a>
    <a href="">Link 3</a>
    <a href="">Link 4</a>
    <a href="">Link 5</a>
  </outer-component>

But it's being rendered with Link 1 at the end: image

Strangely, I can use the same HTML in a non-Angular setting and it renders in order: https://github.com/mattdsteele/mattdsteele-stencil-bug-1/blob/master/src/index.html#L14

This occurs in StackBlitz as well as the vanilla Angular CLI. My guess is that it's related to how Angular generates its template using appendChild, but I haven't been able to figure it out.

Workaround

I do have a workaround - if I convert <inner-component> into a functional component, it works:

export const Inner = (props) => props.children;

export class OuterComponent {
  render() {
    return (
      <Inner>
        <slot />
      </Inner>
    );
  }
}
splitinfinities commented 6 years ago

EDIT: I'm using Stencil v0.9.1, and have also experienced this in ~0.8.0 versions.

I have a similar issue but without using Angular:

All of my copy-wrap's switch the first item to the end, as seen on the home page: https://www-ewncunnboa.now.sh

screen shot 2018-06-11 at 11 09 00 am

The lead in on the accordion: https://www-ewncunnboa.now.sh/accordion.html (view source: view-source:https://www-ewncunnboa.now.sh/accordion.html)

screen shot 2018-06-11 at 11 08 45 am

On this markdown page, I switched the order of the h1 and h3 tags: https://www-ewncunnboa.now.sh/markdown.html

screen shot 2018-06-11 at 11 08 34 am

The copy-wrap component is dead simple, as well as with Matt's example, it's only a simple slotted component:

import { Component, Prop } from '@stencil/core';

@Component({
  tag: 'copy-wrap',
  styleUrl: 'copy-wrap.css'
})
export class CopyWrap {
  @Prop({reflectToAttr: true}) align: string = "left";
  @Prop({reflectToAttr: true}) full: boolean = false;

  render () {
    return (
      <slot />
    );
  }
}
mattdsteele commented 6 years ago

@splitinfinities Interesting that it's happening in Chrome - my issue is happening everywhere except Chrome. 🙃

Is Stellar's source available somewhere? I can try reproducing/building a Karma test case.

ionitron-bot[bot] commented 6 years ago

Thanks for the issue! This issue is being closed due to inactivity. If this is still an issue with the latest version of Stencil, please create a new issue and ensure the template is fully filled out.

Thank you for using Stencil!