1
votes

I've created a new project using the stencil component starter. Inside my component I'm using an external JS nouislider, which injects HTML elements into my div (this.slider ref):

...
componentDidLoad() {
  noUiSlider.create(this.slider, {
    start: [20, 80],
    range: {
      'min': 0,
      'max': 100
    }
  })
}
...

I've copied the slider's CSS into my-component.css and rewrote everything with :host selectors for the shadow dom:

:host(.my-component) .noUi-target {
    position: relative;
    direction: ltr
}

Everything works fine on Chrome/Firefox but the slider styles are not working on IE11/Edge because Stencil appends a helper sc-my-component class to every element that I have inside the render method and generates CSS rules like so:

.my-component.sc-my-component-h .noUi-target.sc-my-component {
  position: relative;
  direction: ltr
}

but the injected nouislider child HTML elements don't have the helper classes on them. I have an ugly fix for this case atm:

...
componentDidLoad() {
  noUiSlider.create(this.slider, {
    start: [20, 80],
    range: {
      'min': 0,
      'max': 100
    }
  })
  this.slider.querySelectorAll('div').forEach((child)=>{
    child.classList.add('sc-my-component')
  })
}
...

I'm appending the helper classes after the slider is created (the slider generates child divs only). Is there a better way to tell Stencil that I'm injecting elements inside lifecycle methods and that it needs to recognize those elements when CSS rules are being generated?

2
From the browser suppot page of Stencil, it seems that we need polyfills to support Shadow Dom in IE and Edge. You could refer to this page about adding polyfills for IE 11 and adding Custom Elements v1 polyfill for Edge to see if it helps.Yu Zhou

2 Answers

0
votes

This is not an answer to your question, nevertheless this could also be interesting for you:

We are currently working on the same topic (StencilJS, shadow: true, noUiSlider) and encountered the problem, that the slider's touch events are not working correctly in shadowDOM on mobile devices. We found a solution for this and already created a PR (https://github.com/leongersen/noUiSlider/pull/1060).

0
votes

I too had problems using nouislider in StencilJS but just managed to make it work.

my-slider.scss

 @import '~nouislider/distribute/nouislider.css';

 :host {
     padding: 50px 30px;
     display: block;
 }

my-slider.tsx

import { Component, h, Prop, Event, EventEmitter } from '@stencil/core';
import noUiSlider from "nouislider";


@Component({
    tag: 'skim-slider',
    styleUrl: 'skim-slider.scss',
    shadow: true
})
export class SkimSlider {

    @Prop() min!: number;
    @Prop() max!: number;

    private slider: HTMLElement;

    @Event() update: EventEmitter;

    componentDidLoad() {
        const slider = noUiSlider.create(this.slider, {
            start: [this.min, this.max],
            tooltips: [true, true],
            range: {
                'min': this.min,
                'max': this.max
            }
        });
        slider.on('change', (value) => this.update.emit(value));
    }

    render() {
        return (
            <div ref={e => this.slider = e}></div>
        );
    }
}

The trick that did it for me was 'display: block'