Elements declared in HTML after Custom Element do not render









up vote
1
down vote

favorite












REAL BIG EDIT:
Hello there, this is edit number 3. This one is here on top because, well, it changes the fundamental question of this post.
In short, I tried putting h1s both before and after a single Custom Element. Well... only what I have putted before rendered. So, I guess the problem is that no elements are rendered after my Custom Elements.
I'm not deleting my old observations below for recording purposes, since someone may happen to strumble in this problem and understand it wrong, like me.




I'm trying a little bit with Custom Elements v1 on Chrome but things aren't quite right.



The custom element in question - I call it range-slider - is just a bunch of 1 label, 1 input range and 1 input number put together and styled, plus number and range are bind to each other.



RangeSlider.js:



class RangeSlider extends HTMLElement 
constructor()
super();

connectedCallback()
this.initShadowDom();
this.flowInputToElem("field", "slider");
this.flowInputToElem("slider", "field");


initShadowDom()
const shadowRoot = this.attachShadow(mode: "open");
shadowRoot.innerHTML = this.template;

flowInputToElem(inputId, elemId)
const shadowRoot = this.shadowRoot;
const input = shadowRoot.getElementById(inputId);
const elem = shadowRoot.getElementById(elemId);

input.addEventListener("input", e =>
const min = parseFloat(elem.min);
const max = parseFloat(elem.max);
const newVal = parseFloat(input.value);

elem.value = newVal > max
? max
: newVal < min
? min
: newVal;
);


get label()
return this.getAttribute("label")
get min()
get max()
return this.getAttribute("max");

get value()

get template()
return `
<style>
@import url('style/appearance.css');
@import url('style/color.css');
@import url('style/size.css');
@import url('style/position.css');
@import url('components/rangeSlider/style/slider.css');
</style>
<form class="w-max arial">
<label for="field">$this.label:</label>
<div class="flx flx-middle">
<input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider
w-big">
<input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none
spin-none brd-none w-small bg-transp txt-center">
</div>
</form>
`;



window.customElements.define('range-slider', RangeSlider);


In my understanding, everything seems to be fine with range-slider. In fact, it works; well, kind of. If I put more than 1 range-slider on my index.html, only the first one is rendered.



index.html:



<!DOCTYPE html>
<html>
<head>
<title>Pegada de carbono</title>
<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" type="text/css" href="style/position.css">
<link rel="stylesheet" type="text/css" href="style/color.css">
<link rel="stylesheet" type="text/css" href="style/size.css">

<script src="components/rangeSlider/RangeSlider.js"></script>
</head>
<body class="pos-abs h-fill w-fill mrg-none pdg-none bg-white">
<range-slider label="example 1" min="0" max="100" value="25"></range-slider>
<range-slider label="example 2" min="0" max="100" value="45"></range-slider>
<range-slider label="example 3" min="0" max="100" value="65"></range-slider>
</body>
</html>


Chrome:
Only the first range-slider happened to render



Why is that?



EDIT:
Strangely enough, when I append the element by JavaScript it renders as expected.



const rangeSlider = document.createElement("range-slider");
rangeSlider.label = "example 4";
rangeSlider.value = "65";
rangeSlider.max = "1000";
rangeSlider.min = "0";

document.body.appendChild(rangeSlider);


EDIT 2:
Okay, I have done some more testing and weirder things happened:
1. if I put 1 native element then 1 range-slider (or vice-versa),
everything renders okay;
2. if I put range-slider, native component then another range-slider, only the first range-slider renders; (which means not even the native component is okay)
3. if I try to add range-sliders inside another Custom Element, the outer Custom Element is good and range-slider number 1 too, but all the other range-sliders are not.










share|improve this question























  • Updated post with some more details.
    – Henrique Guerra
    Nov 11 at 4:08










  • Updated the post to address new question. In short, I thought that I was having problems to render N-ary Custom Elements. After some tests, it seems that I'm not capable of rendering any elements declared by HTML after a Custom one.
    – Henrique Guerra
    Nov 11 at 5:04














up vote
1
down vote

favorite












REAL BIG EDIT:
Hello there, this is edit number 3. This one is here on top because, well, it changes the fundamental question of this post.
In short, I tried putting h1s both before and after a single Custom Element. Well... only what I have putted before rendered. So, I guess the problem is that no elements are rendered after my Custom Elements.
I'm not deleting my old observations below for recording purposes, since someone may happen to strumble in this problem and understand it wrong, like me.




I'm trying a little bit with Custom Elements v1 on Chrome but things aren't quite right.



The custom element in question - I call it range-slider - is just a bunch of 1 label, 1 input range and 1 input number put together and styled, plus number and range are bind to each other.



RangeSlider.js:



class RangeSlider extends HTMLElement 
constructor()
super();

connectedCallback()
this.initShadowDom();
this.flowInputToElem("field", "slider");
this.flowInputToElem("slider", "field");


initShadowDom()
const shadowRoot = this.attachShadow(mode: "open");
shadowRoot.innerHTML = this.template;

flowInputToElem(inputId, elemId)
const shadowRoot = this.shadowRoot;
const input = shadowRoot.getElementById(inputId);
const elem = shadowRoot.getElementById(elemId);

input.addEventListener("input", e =>
const min = parseFloat(elem.min);
const max = parseFloat(elem.max);
const newVal = parseFloat(input.value);

elem.value = newVal > max
? max
: newVal < min
? min
: newVal;
);


get label()
return this.getAttribute("label")
get min()
get max()
return this.getAttribute("max");

get value()

get template()
return `
<style>
@import url('style/appearance.css');
@import url('style/color.css');
@import url('style/size.css');
@import url('style/position.css');
@import url('components/rangeSlider/style/slider.css');
</style>
<form class="w-max arial">
<label for="field">$this.label:</label>
<div class="flx flx-middle">
<input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider
w-big">
<input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none
spin-none brd-none w-small bg-transp txt-center">
</div>
</form>
`;



window.customElements.define('range-slider', RangeSlider);


In my understanding, everything seems to be fine with range-slider. In fact, it works; well, kind of. If I put more than 1 range-slider on my index.html, only the first one is rendered.



index.html:



<!DOCTYPE html>
<html>
<head>
<title>Pegada de carbono</title>
<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" type="text/css" href="style/position.css">
<link rel="stylesheet" type="text/css" href="style/color.css">
<link rel="stylesheet" type="text/css" href="style/size.css">

<script src="components/rangeSlider/RangeSlider.js"></script>
</head>
<body class="pos-abs h-fill w-fill mrg-none pdg-none bg-white">
<range-slider label="example 1" min="0" max="100" value="25"></range-slider>
<range-slider label="example 2" min="0" max="100" value="45"></range-slider>
<range-slider label="example 3" min="0" max="100" value="65"></range-slider>
</body>
</html>


Chrome:
Only the first range-slider happened to render



Why is that?



EDIT:
Strangely enough, when I append the element by JavaScript it renders as expected.



const rangeSlider = document.createElement("range-slider");
rangeSlider.label = "example 4";
rangeSlider.value = "65";
rangeSlider.max = "1000";
rangeSlider.min = "0";

document.body.appendChild(rangeSlider);


EDIT 2:
Okay, I have done some more testing and weirder things happened:
1. if I put 1 native element then 1 range-slider (or vice-versa),
everything renders okay;
2. if I put range-slider, native component then another range-slider, only the first range-slider renders; (which means not even the native component is okay)
3. if I try to add range-sliders inside another Custom Element, the outer Custom Element is good and range-slider number 1 too, but all the other range-sliders are not.










share|improve this question























  • Updated post with some more details.
    – Henrique Guerra
    Nov 11 at 4:08










  • Updated the post to address new question. In short, I thought that I was having problems to render N-ary Custom Elements. After some tests, it seems that I'm not capable of rendering any elements declared by HTML after a Custom one.
    – Henrique Guerra
    Nov 11 at 5:04












up vote
1
down vote

favorite









up vote
1
down vote

favorite











REAL BIG EDIT:
Hello there, this is edit number 3. This one is here on top because, well, it changes the fundamental question of this post.
In short, I tried putting h1s both before and after a single Custom Element. Well... only what I have putted before rendered. So, I guess the problem is that no elements are rendered after my Custom Elements.
I'm not deleting my old observations below for recording purposes, since someone may happen to strumble in this problem and understand it wrong, like me.




I'm trying a little bit with Custom Elements v1 on Chrome but things aren't quite right.



The custom element in question - I call it range-slider - is just a bunch of 1 label, 1 input range and 1 input number put together and styled, plus number and range are bind to each other.



RangeSlider.js:



class RangeSlider extends HTMLElement 
constructor()
super();

connectedCallback()
this.initShadowDom();
this.flowInputToElem("field", "slider");
this.flowInputToElem("slider", "field");


initShadowDom()
const shadowRoot = this.attachShadow(mode: "open");
shadowRoot.innerHTML = this.template;

flowInputToElem(inputId, elemId)
const shadowRoot = this.shadowRoot;
const input = shadowRoot.getElementById(inputId);
const elem = shadowRoot.getElementById(elemId);

input.addEventListener("input", e =>
const min = parseFloat(elem.min);
const max = parseFloat(elem.max);
const newVal = parseFloat(input.value);

elem.value = newVal > max
? max
: newVal < min
? min
: newVal;
);


get label()
return this.getAttribute("label")
get min()
get max()
return this.getAttribute("max");

get value()

get template()
return `
<style>
@import url('style/appearance.css');
@import url('style/color.css');
@import url('style/size.css');
@import url('style/position.css');
@import url('components/rangeSlider/style/slider.css');
</style>
<form class="w-max arial">
<label for="field">$this.label:</label>
<div class="flx flx-middle">
<input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider
w-big">
<input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none
spin-none brd-none w-small bg-transp txt-center">
</div>
</form>
`;



window.customElements.define('range-slider', RangeSlider);


In my understanding, everything seems to be fine with range-slider. In fact, it works; well, kind of. If I put more than 1 range-slider on my index.html, only the first one is rendered.



index.html:



<!DOCTYPE html>
<html>
<head>
<title>Pegada de carbono</title>
<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" type="text/css" href="style/position.css">
<link rel="stylesheet" type="text/css" href="style/color.css">
<link rel="stylesheet" type="text/css" href="style/size.css">

<script src="components/rangeSlider/RangeSlider.js"></script>
</head>
<body class="pos-abs h-fill w-fill mrg-none pdg-none bg-white">
<range-slider label="example 1" min="0" max="100" value="25"></range-slider>
<range-slider label="example 2" min="0" max="100" value="45"></range-slider>
<range-slider label="example 3" min="0" max="100" value="65"></range-slider>
</body>
</html>


Chrome:
Only the first range-slider happened to render



Why is that?



EDIT:
Strangely enough, when I append the element by JavaScript it renders as expected.



const rangeSlider = document.createElement("range-slider");
rangeSlider.label = "example 4";
rangeSlider.value = "65";
rangeSlider.max = "1000";
rangeSlider.min = "0";

document.body.appendChild(rangeSlider);


EDIT 2:
Okay, I have done some more testing and weirder things happened:
1. if I put 1 native element then 1 range-slider (or vice-versa),
everything renders okay;
2. if I put range-slider, native component then another range-slider, only the first range-slider renders; (which means not even the native component is okay)
3. if I try to add range-sliders inside another Custom Element, the outer Custom Element is good and range-slider number 1 too, but all the other range-sliders are not.










share|improve this question















REAL BIG EDIT:
Hello there, this is edit number 3. This one is here on top because, well, it changes the fundamental question of this post.
In short, I tried putting h1s both before and after a single Custom Element. Well... only what I have putted before rendered. So, I guess the problem is that no elements are rendered after my Custom Elements.
I'm not deleting my old observations below for recording purposes, since someone may happen to strumble in this problem and understand it wrong, like me.




I'm trying a little bit with Custom Elements v1 on Chrome but things aren't quite right.



The custom element in question - I call it range-slider - is just a bunch of 1 label, 1 input range and 1 input number put together and styled, plus number and range are bind to each other.



RangeSlider.js:



class RangeSlider extends HTMLElement 
constructor()
super();

connectedCallback()
this.initShadowDom();
this.flowInputToElem("field", "slider");
this.flowInputToElem("slider", "field");


initShadowDom()
const shadowRoot = this.attachShadow(mode: "open");
shadowRoot.innerHTML = this.template;

flowInputToElem(inputId, elemId)
const shadowRoot = this.shadowRoot;
const input = shadowRoot.getElementById(inputId);
const elem = shadowRoot.getElementById(elemId);

input.addEventListener("input", e =>
const min = parseFloat(elem.min);
const max = parseFloat(elem.max);
const newVal = parseFloat(input.value);

elem.value = newVal > max
? max
: newVal < min
? min
: newVal;
);


get label()
return this.getAttribute("label")
get min()
get max()
return this.getAttribute("max");

get value()

get template()
return `
<style>
@import url('style/appearance.css');
@import url('style/color.css');
@import url('style/size.css');
@import url('style/position.css');
@import url('components/rangeSlider/style/slider.css');
</style>
<form class="w-max arial">
<label for="field">$this.label:</label>
<div class="flx flx-middle">
<input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider
w-big">
<input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none
spin-none brd-none w-small bg-transp txt-center">
</div>
</form>
`;



window.customElements.define('range-slider', RangeSlider);


In my understanding, everything seems to be fine with range-slider. In fact, it works; well, kind of. If I put more than 1 range-slider on my index.html, only the first one is rendered.



index.html:



<!DOCTYPE html>
<html>
<head>
<title>Pegada de carbono</title>
<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" type="text/css" href="style/position.css">
<link rel="stylesheet" type="text/css" href="style/color.css">
<link rel="stylesheet" type="text/css" href="style/size.css">

<script src="components/rangeSlider/RangeSlider.js"></script>
</head>
<body class="pos-abs h-fill w-fill mrg-none pdg-none bg-white">
<range-slider label="example 1" min="0" max="100" value="25"></range-slider>
<range-slider label="example 2" min="0" max="100" value="45"></range-slider>
<range-slider label="example 3" min="0" max="100" value="65"></range-slider>
</body>
</html>


Chrome:
Only the first range-slider happened to render



Why is that?



EDIT:
Strangely enough, when I append the element by JavaScript it renders as expected.



const rangeSlider = document.createElement("range-slider");
rangeSlider.label = "example 4";
rangeSlider.value = "65";
rangeSlider.max = "1000";
rangeSlider.min = "0";

document.body.appendChild(rangeSlider);


EDIT 2:
Okay, I have done some more testing and weirder things happened:
1. if I put 1 native element then 1 range-slider (or vice-versa),
everything renders okay;
2. if I put range-slider, native component then another range-slider, only the first range-slider renders; (which means not even the native component is okay)
3. if I try to add range-sliders inside another Custom Element, the outer Custom Element is good and range-slider number 1 too, but all the other range-sliders are not.







javascript html google-chrome shadow-dom custom-element






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 11 at 5:01

























asked Nov 10 at 22:45









Henrique Guerra

187




187











  • Updated post with some more details.
    – Henrique Guerra
    Nov 11 at 4:08










  • Updated the post to address new question. In short, I thought that I was having problems to render N-ary Custom Elements. After some tests, it seems that I'm not capable of rendering any elements declared by HTML after a Custom one.
    – Henrique Guerra
    Nov 11 at 5:04
















  • Updated post with some more details.
    – Henrique Guerra
    Nov 11 at 4:08










  • Updated the post to address new question. In short, I thought that I was having problems to render N-ary Custom Elements. After some tests, it seems that I'm not capable of rendering any elements declared by HTML after a Custom one.
    – Henrique Guerra
    Nov 11 at 5:04















Updated post with some more details.
– Henrique Guerra
Nov 11 at 4:08




Updated post with some more details.
– Henrique Guerra
Nov 11 at 4:08












Updated the post to address new question. In short, I thought that I was having problems to render N-ary Custom Elements. After some tests, it seems that I'm not capable of rendering any elements declared by HTML after a Custom one.
– Henrique Guerra
Nov 11 at 5:04




Updated the post to address new question. In short, I thought that I was having problems to render N-ary Custom Elements. After some tests, it seems that I'm not capable of rendering any elements declared by HTML after a Custom one.
– Henrique Guerra
Nov 11 at 5:04












1 Answer
1






active

oldest

votes

















up vote
0
down vote













I took your code and modified it slightly and ran in in the snippet mode here on this page and it worked fine.






 class OtherEl extends HTMLElement 
constructor()
super();

this.attachShadow(mode: "open").innerHTML = '<div style="background-color: yellow;padding:4px;"><range-slider label="inner slider" min="0" max="100" value="5"></range-slider></div>';



window.customElements.define('other-el', OtherEl);

class RangeSlider extends HTMLElement
constructor()
super();
this.attachShadow(mode: "open");


connectedCallback()
if (this.shadowRoot.childElementCount === 0)
this.shadowRoot.innerHTML = this.template;
this.flowInputToElem("field", "slider");
this.flowInputToElem("slider", "field");



flowInputToElem(inputId, elemId)
const shadowRoot = this.shadowRoot;
const input = shadowRoot.getElementById(inputId);
const elem = shadowRoot.getElementById(elemId);

input.addEventListener("input", e =>
const min = elem.min;
const max = elem.max;
const newVal = input.value;
elem.value = newVal > max ? max : newVal < min ? min : newVal;
);


get label() "Range slider";

get min()
return parseFloat(this.getAttribute("min")
get max() '100');

get value() '0');


get template()
return `
<style>
@import url('style/appearance.css');
@import url('style/color.css');
@import url('style/size.css');
@import url('style/position.css');
@import url('components/rangeSlider/style/slider.css');
</style>
<form class="w-max arial">
<label for="field">$this.label:</label>
<div class="flx flx-middle">
<input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
<input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
</div>
</form>
`;



window.customElements.define('range-slider', RangeSlider);

 <h1>Before</h1>
<range-slider label="example 1" min="0" max="100" value="25"></range-slider>
<h2>After 1</h2>
<range-slider label="example 2" min="0" max="100" value="45"></range-slider>
<h2>After 2</h2>
<range-slider label="example 3" min="0" max="100" value="65"></range-slider>
<h2>After 3</h2>
<other-el></other-el>
<h2>After OtherEl</h2>





Then I ran it on my server and saw what you were seeing. Only one element showed.



Only one showing



But I noticed this error in the dev tools:



enter image description here



Since I don't have your CSS files my CSS is not loading and this is causing something to crash in the Web Component code.



When I commented out the <style> tag in your template:






 get template() 
return `
<!-- <style>
@import url('style/appearance.css');
@import url('style/color.css');
@import url('style/size.css');
@import url('style/position.css');
@import url('components/rangeSlider/style/slider.css');
</style> -->
<form class="w-max arial">
<label for="field">$this.label:</label>
<div class="flx flx-middle">
<input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
<input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
</div>
</form>
`;

}





Then all 5 show up, including the one inside my other element.



enter image description here






share|improve this answer




















    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53244167%2felements-declared-in-html-after-custom-element-do-not-render%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote













    I took your code and modified it slightly and ran in in the snippet mode here on this page and it worked fine.






     class OtherEl extends HTMLElement 
    constructor()
    super();

    this.attachShadow(mode: "open").innerHTML = '<div style="background-color: yellow;padding:4px;"><range-slider label="inner slider" min="0" max="100" value="5"></range-slider></div>';



    window.customElements.define('other-el', OtherEl);

    class RangeSlider extends HTMLElement
    constructor()
    super();
    this.attachShadow(mode: "open");


    connectedCallback()
    if (this.shadowRoot.childElementCount === 0)
    this.shadowRoot.innerHTML = this.template;
    this.flowInputToElem("field", "slider");
    this.flowInputToElem("slider", "field");



    flowInputToElem(inputId, elemId)
    const shadowRoot = this.shadowRoot;
    const input = shadowRoot.getElementById(inputId);
    const elem = shadowRoot.getElementById(elemId);

    input.addEventListener("input", e =>
    const min = elem.min;
    const max = elem.max;
    const newVal = input.value;
    elem.value = newVal > max ? max : newVal < min ? min : newVal;
    );


    get label() "Range slider";

    get min()
    return parseFloat(this.getAttribute("min")
    get max() '100');

    get value() '0');


    get template()
    return `
    <style>
    @import url('style/appearance.css');
    @import url('style/color.css');
    @import url('style/size.css');
    @import url('style/position.css');
    @import url('components/rangeSlider/style/slider.css');
    </style>
    <form class="w-max arial">
    <label for="field">$this.label:</label>
    <div class="flx flx-middle">
    <input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
    <input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
    </div>
    </form>
    `;



    window.customElements.define('range-slider', RangeSlider);

     <h1>Before</h1>
    <range-slider label="example 1" min="0" max="100" value="25"></range-slider>
    <h2>After 1</h2>
    <range-slider label="example 2" min="0" max="100" value="45"></range-slider>
    <h2>After 2</h2>
    <range-slider label="example 3" min="0" max="100" value="65"></range-slider>
    <h2>After 3</h2>
    <other-el></other-el>
    <h2>After OtherEl</h2>





    Then I ran it on my server and saw what you were seeing. Only one element showed.



    Only one showing



    But I noticed this error in the dev tools:



    enter image description here



    Since I don't have your CSS files my CSS is not loading and this is causing something to crash in the Web Component code.



    When I commented out the <style> tag in your template:






     get template() 
    return `
    <!-- <style>
    @import url('style/appearance.css');
    @import url('style/color.css');
    @import url('style/size.css');
    @import url('style/position.css');
    @import url('components/rangeSlider/style/slider.css');
    </style> -->
    <form class="w-max arial">
    <label for="field">$this.label:</label>
    <div class="flx flx-middle">
    <input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
    <input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
    </div>
    </form>
    `;

    }





    Then all 5 show up, including the one inside my other element.



    enter image description here






    share|improve this answer
























      up vote
      0
      down vote













      I took your code and modified it slightly and ran in in the snippet mode here on this page and it worked fine.






       class OtherEl extends HTMLElement 
      constructor()
      super();

      this.attachShadow(mode: "open").innerHTML = '<div style="background-color: yellow;padding:4px;"><range-slider label="inner slider" min="0" max="100" value="5"></range-slider></div>';



      window.customElements.define('other-el', OtherEl);

      class RangeSlider extends HTMLElement
      constructor()
      super();
      this.attachShadow(mode: "open");


      connectedCallback()
      if (this.shadowRoot.childElementCount === 0)
      this.shadowRoot.innerHTML = this.template;
      this.flowInputToElem("field", "slider");
      this.flowInputToElem("slider", "field");



      flowInputToElem(inputId, elemId)
      const shadowRoot = this.shadowRoot;
      const input = shadowRoot.getElementById(inputId);
      const elem = shadowRoot.getElementById(elemId);

      input.addEventListener("input", e =>
      const min = elem.min;
      const max = elem.max;
      const newVal = input.value;
      elem.value = newVal > max ? max : newVal < min ? min : newVal;
      );


      get label() "Range slider";

      get min()
      return parseFloat(this.getAttribute("min")
      get max() '100');

      get value() '0');


      get template()
      return `
      <style>
      @import url('style/appearance.css');
      @import url('style/color.css');
      @import url('style/size.css');
      @import url('style/position.css');
      @import url('components/rangeSlider/style/slider.css');
      </style>
      <form class="w-max arial">
      <label for="field">$this.label:</label>
      <div class="flx flx-middle">
      <input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
      <input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
      </div>
      </form>
      `;



      window.customElements.define('range-slider', RangeSlider);

       <h1>Before</h1>
      <range-slider label="example 1" min="0" max="100" value="25"></range-slider>
      <h2>After 1</h2>
      <range-slider label="example 2" min="0" max="100" value="45"></range-slider>
      <h2>After 2</h2>
      <range-slider label="example 3" min="0" max="100" value="65"></range-slider>
      <h2>After 3</h2>
      <other-el></other-el>
      <h2>After OtherEl</h2>





      Then I ran it on my server and saw what you were seeing. Only one element showed.



      Only one showing



      But I noticed this error in the dev tools:



      enter image description here



      Since I don't have your CSS files my CSS is not loading and this is causing something to crash in the Web Component code.



      When I commented out the <style> tag in your template:






       get template() 
      return `
      <!-- <style>
      @import url('style/appearance.css');
      @import url('style/color.css');
      @import url('style/size.css');
      @import url('style/position.css');
      @import url('components/rangeSlider/style/slider.css');
      </style> -->
      <form class="w-max arial">
      <label for="field">$this.label:</label>
      <div class="flx flx-middle">
      <input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
      <input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
      </div>
      </form>
      `;

      }





      Then all 5 show up, including the one inside my other element.



      enter image description here






      share|improve this answer






















        up vote
        0
        down vote










        up vote
        0
        down vote









        I took your code and modified it slightly and ran in in the snippet mode here on this page and it worked fine.






         class OtherEl extends HTMLElement 
        constructor()
        super();

        this.attachShadow(mode: "open").innerHTML = '<div style="background-color: yellow;padding:4px;"><range-slider label="inner slider" min="0" max="100" value="5"></range-slider></div>';



        window.customElements.define('other-el', OtherEl);

        class RangeSlider extends HTMLElement
        constructor()
        super();
        this.attachShadow(mode: "open");


        connectedCallback()
        if (this.shadowRoot.childElementCount === 0)
        this.shadowRoot.innerHTML = this.template;
        this.flowInputToElem("field", "slider");
        this.flowInputToElem("slider", "field");



        flowInputToElem(inputId, elemId)
        const shadowRoot = this.shadowRoot;
        const input = shadowRoot.getElementById(inputId);
        const elem = shadowRoot.getElementById(elemId);

        input.addEventListener("input", e =>
        const min = elem.min;
        const max = elem.max;
        const newVal = input.value;
        elem.value = newVal > max ? max : newVal < min ? min : newVal;
        );


        get label() "Range slider";

        get min()
        return parseFloat(this.getAttribute("min")
        get max() '100');

        get value() '0');


        get template()
        return `
        <style>
        @import url('style/appearance.css');
        @import url('style/color.css');
        @import url('style/size.css');
        @import url('style/position.css');
        @import url('components/rangeSlider/style/slider.css');
        </style>
        <form class="w-max arial">
        <label for="field">$this.label:</label>
        <div class="flx flx-middle">
        <input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
        <input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
        </div>
        </form>
        `;



        window.customElements.define('range-slider', RangeSlider);

         <h1>Before</h1>
        <range-slider label="example 1" min="0" max="100" value="25"></range-slider>
        <h2>After 1</h2>
        <range-slider label="example 2" min="0" max="100" value="45"></range-slider>
        <h2>After 2</h2>
        <range-slider label="example 3" min="0" max="100" value="65"></range-slider>
        <h2>After 3</h2>
        <other-el></other-el>
        <h2>After OtherEl</h2>





        Then I ran it on my server and saw what you were seeing. Only one element showed.



        Only one showing



        But I noticed this error in the dev tools:



        enter image description here



        Since I don't have your CSS files my CSS is not loading and this is causing something to crash in the Web Component code.



        When I commented out the <style> tag in your template:






         get template() 
        return `
        <!-- <style>
        @import url('style/appearance.css');
        @import url('style/color.css');
        @import url('style/size.css');
        @import url('style/position.css');
        @import url('components/rangeSlider/style/slider.css');
        </style> -->
        <form class="w-max arial">
        <label for="field">$this.label:</label>
        <div class="flx flx-middle">
        <input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
        <input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
        </div>
        </form>
        `;

        }





        Then all 5 show up, including the one inside my other element.



        enter image description here






        share|improve this answer












        I took your code and modified it slightly and ran in in the snippet mode here on this page and it worked fine.






         class OtherEl extends HTMLElement 
        constructor()
        super();

        this.attachShadow(mode: "open").innerHTML = '<div style="background-color: yellow;padding:4px;"><range-slider label="inner slider" min="0" max="100" value="5"></range-slider></div>';



        window.customElements.define('other-el', OtherEl);

        class RangeSlider extends HTMLElement
        constructor()
        super();
        this.attachShadow(mode: "open");


        connectedCallback()
        if (this.shadowRoot.childElementCount === 0)
        this.shadowRoot.innerHTML = this.template;
        this.flowInputToElem("field", "slider");
        this.flowInputToElem("slider", "field");



        flowInputToElem(inputId, elemId)
        const shadowRoot = this.shadowRoot;
        const input = shadowRoot.getElementById(inputId);
        const elem = shadowRoot.getElementById(elemId);

        input.addEventListener("input", e =>
        const min = elem.min;
        const max = elem.max;
        const newVal = input.value;
        elem.value = newVal > max ? max : newVal < min ? min : newVal;
        );


        get label() "Range slider";

        get min()
        return parseFloat(this.getAttribute("min")
        get max() '100');

        get value() '0');


        get template()
        return `
        <style>
        @import url('style/appearance.css');
        @import url('style/color.css');
        @import url('style/size.css');
        @import url('style/position.css');
        @import url('components/rangeSlider/style/slider.css');
        </style>
        <form class="w-max arial">
        <label for="field">$this.label:</label>
        <div class="flx flx-middle">
        <input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
        <input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
        </div>
        </form>
        `;



        window.customElements.define('range-slider', RangeSlider);

         <h1>Before</h1>
        <range-slider label="example 1" min="0" max="100" value="25"></range-slider>
        <h2>After 1</h2>
        <range-slider label="example 2" min="0" max="100" value="45"></range-slider>
        <h2>After 2</h2>
        <range-slider label="example 3" min="0" max="100" value="65"></range-slider>
        <h2>After 3</h2>
        <other-el></other-el>
        <h2>After OtherEl</h2>





        Then I ran it on my server and saw what you were seeing. Only one element showed.



        Only one showing



        But I noticed this error in the dev tools:



        enter image description here



        Since I don't have your CSS files my CSS is not loading and this is causing something to crash in the Web Component code.



        When I commented out the <style> tag in your template:






         get template() 
        return `
        <!-- <style>
        @import url('style/appearance.css');
        @import url('style/color.css');
        @import url('style/size.css');
        @import url('style/position.css');
        @import url('components/rangeSlider/style/slider.css');
        </style> -->
        <form class="w-max arial">
        <label for="field">$this.label:</label>
        <div class="flx flx-middle">
        <input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
        <input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
        </div>
        </form>
        `;

        }





        Then all 5 show up, including the one inside my other element.



        enter image description here






         class OtherEl extends HTMLElement 
        constructor()
        super();

        this.attachShadow(mode: "open").innerHTML = '<div style="background-color: yellow;padding:4px;"><range-slider label="inner slider" min="0" max="100" value="5"></range-slider></div>';



        window.customElements.define('other-el', OtherEl);

        class RangeSlider extends HTMLElement
        constructor()
        super();
        this.attachShadow(mode: "open");


        connectedCallback()
        if (this.shadowRoot.childElementCount === 0)
        this.shadowRoot.innerHTML = this.template;
        this.flowInputToElem("field", "slider");
        this.flowInputToElem("slider", "field");



        flowInputToElem(inputId, elemId)
        const shadowRoot = this.shadowRoot;
        const input = shadowRoot.getElementById(inputId);
        const elem = shadowRoot.getElementById(elemId);

        input.addEventListener("input", e =>
        const min = elem.min;
        const max = elem.max;
        const newVal = input.value;
        elem.value = newVal > max ? max : newVal < min ? min : newVal;
        );


        get label() "Range slider";

        get min()
        return parseFloat(this.getAttribute("min")
        get max() '100');

        get value() '0');


        get template()
        return `
        <style>
        @import url('style/appearance.css');
        @import url('style/color.css');
        @import url('style/size.css');
        @import url('style/position.css');
        @import url('components/rangeSlider/style/slider.css');
        </style>
        <form class="w-max arial">
        <label for="field">$this.label:</label>
        <div class="flx flx-middle">
        <input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
        <input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
        </div>
        </form>
        `;



        window.customElements.define('range-slider', RangeSlider);

         <h1>Before</h1>
        <range-slider label="example 1" min="0" max="100" value="25"></range-slider>
        <h2>After 1</h2>
        <range-slider label="example 2" min="0" max="100" value="45"></range-slider>
        <h2>After 2</h2>
        <range-slider label="example 3" min="0" max="100" value="65"></range-slider>
        <h2>After 3</h2>
        <other-el></other-el>
        <h2>After OtherEl</h2>





         class OtherEl extends HTMLElement 
        constructor()
        super();

        this.attachShadow(mode: "open").innerHTML = '<div style="background-color: yellow;padding:4px;"><range-slider label="inner slider" min="0" max="100" value="5"></range-slider></div>';



        window.customElements.define('other-el', OtherEl);

        class RangeSlider extends HTMLElement
        constructor()
        super();
        this.attachShadow(mode: "open");


        connectedCallback()
        if (this.shadowRoot.childElementCount === 0)
        this.shadowRoot.innerHTML = this.template;
        this.flowInputToElem("field", "slider");
        this.flowInputToElem("slider", "field");



        flowInputToElem(inputId, elemId)
        const shadowRoot = this.shadowRoot;
        const input = shadowRoot.getElementById(inputId);
        const elem = shadowRoot.getElementById(elemId);

        input.addEventListener("input", e =>
        const min = elem.min;
        const max = elem.max;
        const newVal = input.value;
        elem.value = newVal > max ? max : newVal < min ? min : newVal;
        );


        get label() "Range slider";

        get min()
        return parseFloat(this.getAttribute("min")
        get max() '100');

        get value() '0');


        get template()
        return `
        <style>
        @import url('style/appearance.css');
        @import url('style/color.css');
        @import url('style/size.css');
        @import url('style/position.css');
        @import url('components/rangeSlider/style/slider.css');
        </style>
        <form class="w-max arial">
        <label for="field">$this.label:</label>
        <div class="flx flx-middle">
        <input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
        <input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
        </div>
        </form>
        `;



        window.customElements.define('range-slider', RangeSlider);

         <h1>Before</h1>
        <range-slider label="example 1" min="0" max="100" value="25"></range-slider>
        <h2>After 1</h2>
        <range-slider label="example 2" min="0" max="100" value="45"></range-slider>
        <h2>After 2</h2>
        <range-slider label="example 3" min="0" max="100" value="65"></range-slider>
        <h2>After 3</h2>
        <other-el></other-el>
        <h2>After OtherEl</h2>





         get template() 
        return `
        <!-- <style>
        @import url('style/appearance.css');
        @import url('style/color.css');
        @import url('style/size.css');
        @import url('style/position.css');
        @import url('components/rangeSlider/style/slider.css');
        </style> -->
        <form class="w-max arial">
        <label for="field">$this.label:</label>
        <div class="flx flx-middle">
        <input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
        <input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
        </div>
        </form>
        `;

        }





         get template() 
        return `
        <!-- <style>
        @import url('style/appearance.css');
        @import url('style/color.css');
        @import url('style/size.css');
        @import url('style/position.css');
        @import url('components/rangeSlider/style/slider.css');
        </style> -->
        <form class="w-max arial">
        <label for="field">$this.label:</label>
        <div class="flx flx-middle">
        <input id="slider" type="range" min="$this.min" max="$this.max" value="$this.value" class="slider w-big">
        <input id="field" type="number" min="0" max="$Infinity" value="$this.value" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
        </div>
        </form>
        `;

        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 12 at 15:25









        Intervalia

        3,81111029




        3,81111029



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53244167%2felements-declared-in-html-after-custom-element-do-not-render%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Top Tejano songwriter Luis Silva dead of heart attack at 64

            ReactJS Fetched API data displays live - need Data displayed static

            Evgeni Malkin