Mobius1/Selectr

Not working inside shadow dom

ZempTime opened this issue · 2 comments

Hey, I'm running into an issue where this isn't working when I'm invoking it inside a shadow root.

Here's a repro: https://stackblitz.com/edit/selectr-exploration?file=index.js

You can't catch the click event in there, but when you do, this is what you see:
screen shot 2019-02-25 at 5 34 29 pm

It opens! It's there! But then it immediately closes. I need to look through the codebase further, but I've got two questions:

  1. You have any idea where this might be happening?
  2. Are you open to PR's around this if a suitable fix is discovered?

One of the issues was, event.target behaves differently with shadow dom.
screen shot 2019-02-26 at 10 08 19 am
This click actually happened on the Selectr component, but the syntax of accessing where the click was obscures it.

To get a true list of all the dom elements the click event has bubbled, you can use event.composedPath()

Updating it to this resolves the issue!

var target = e.target;
var outsideContainer = e.composedPath ? !e.composedPath().includes(this.container) : !this.container.contains(target);
if (outsideContainer && (this.opened || util.hasClass(this.container, "notice"))) {

This... might be it. There might be no more issues, although the right place to look would be other document-level listeners.

Also, the way you approach templates is really similar to: https://lit-html.polymer-project.org/

Next issue I ran into was when setting to "multiple":

selectr.js:1479 Uncaught (in promise) TypeError: Cannot read property 'selected' of undefined
    at Selectr.setSelected (selectr.js:1479)
    at Selectr.build (selectr.js:569)
    at Selectr.render (selectr.js:1061)
    at new Selectr (selectr.js:1003)
    at HTMLElement.firstUpdated (mtzwc-selector.js:236)
    at HTMLElement.performUpdate (updating-element.js:479)
    at HTMLElement._enqueueUpdate (updating-element.js:437)

deleting

        // If we're changing a select-one to select-multiple via the config
        // and there are no selected options, the first option will be selected by the browser
        // Let's prevent that here.
        if (this.config.multiple && this.originalType === "select-one" && !this.config.data) {
            if (this.el.options[0].selected && !this.el.options[0].defaultSelected) {
                this.el.options[0].selected = false;
            }
        }

got us to a working state, but I'm right now only testing on recent versions of chrome/firefox. Might revisit this/re-add this later