javascript - Is it possible to keep the inner html of a custom element? - Stack Overflow

Using Custom Elements, I would like to style the elements inside the custom element, but when I define

Using Custom Elements, I would like to style the elements inside the custom element, but when I define the element, everything besides the shadow dom disappears.

How do I move the content from the element to the shadow dom? I already have a wrapper element (<div class="wrapper">) inside the shadow, but trying to use

wrapper.innerHTML = this.innerHTML;

doesn't work.

HTML

<site-card>
  <section title>
    ...
  </section>
  <section body>
    ...
  </section>
  <section actions>
    <button class="modern small">Action</button>
    <button class="modern small">Action 2</button>
  </section>
</site-card>

JS

"use strict";
class cardElement extends HTMLElement {
    constructor() {
        super();
        var shadow = this.attachShadow({mode: 'open'});
        var wrapper = document.createElement('div');
        wrapper.setAttribute('class','wrapper');
        wrapper.innerHTML = this.innerHTML;
        var style = document.createElement('style');
        style.textContent = ... /* CSS removed to shorten. */
        shadow.appendChild(style);
        shadow.appendChild(wrapper);
    };
};
customElements.define('site-card', cardElement);

Using Custom Elements, I would like to style the elements inside the custom element, but when I define the element, everything besides the shadow dom disappears.

How do I move the content from the element to the shadow dom? I already have a wrapper element (<div class="wrapper">) inside the shadow, but trying to use

wrapper.innerHTML = this.innerHTML;

doesn't work.

HTML

<site-card>
  <section title>
    ...
  </section>
  <section body>
    ...
  </section>
  <section actions>
    <button class="modern small">Action</button>
    <button class="modern small">Action 2</button>
  </section>
</site-card>

JS

"use strict";
class cardElement extends HTMLElement {
    constructor() {
        super();
        var shadow = this.attachShadow({mode: 'open'});
        var wrapper = document.createElement('div');
        wrapper.setAttribute('class','wrapper');
        wrapper.innerHTML = this.innerHTML;
        var style = document.createElement('style');
        style.textContent = ... /* CSS removed to shorten. */
        shadow.appendChild(style);
        shadow.appendChild(wrapper);
    };
};
customElements.define('site-card', cardElement);
Share edited Mar 29, 2019 at 6:39 Christopher Bradshaw 2,7835 gold badges27 silver badges41 bronze badges asked Feb 12, 2018 at 1:43 James MJames M 5611 gold badge5 silver badges7 bronze badges 2
  • Wele to SO. Please include all relevant lines of code, its output and explain the expected result versus what you get. – marekful Commented Feb 12, 2018 at 1:54
  • @marekful Thanks! I have added the HTML and JS. – James M Commented Feb 13, 2018 at 2:46
Add a ment  | 

2 Answers 2

Reset to default 5

If you want to control the CSS from outside of the custom element then just use <slot>. <slot> embeds the children into the slot but leaves CSS control to outside the element.

class cardElement extends HTMLElement {
  constructor() {
    super();
    var shadow = this.attachShadow({mode: 'open'});
    var wrapper = document.createElement('slot');
    var style = document.createElement('style');
    style.textContent = `
    [title] {
      background-color: #060;
      color: #FFF;
    }
    [body] {
      background-color: #600;
      color: #FFF;
    }
    [actions] {
      background-color: #006;
      color: #FFF;
    }
    `;
    shadow.appendChild(style);
    shadow.appendChild(wrapper);
  };
};
customElements.define('site-card', cardElement);
[title] {
  background-color: #0F0;
  color: #000;
}
[body] {
  background-color: #F00;
  color: #000;
}
[actions] {
  background-color: #00F;
  color: #000;
}
<site-card>
  <section title>
    This is the title
  </section>
  <section body>
    This is the body
  </section>
  <section actions>
    <button class="modern small">Action</button>
    <button class="modern small">Action 2</button>
  </section>
</site-card>

If you want to control the CSS from inside the element then you need to migrate the children. But this can not be done in the constructor. This section of the spec explains the limitations on the constructor.

You need to move the children in the connectedCallback

class cardElement extends HTMLElement {
  constructor() {
    super();
    var shadow = this.attachShadow({mode: 'open'});
    this._wrapper = document.createElement('div');
    var style = document.createElement('style');
    style.textContent = `
    [title] {
      background-color: #060;
      color: #FFF;
    }
    [body] {
      background-color: #600;
      color: #FFF;
    }
    [actions] {
      background-color: #006;
      color: #FFF;
    }
    `;
    shadow.appendChild(style);
    shadow.appendChild(this._wrapper);
  };
  
  connectedCallback() {
    while(this.firstElementChild) {
      this._wrapper.appendChild(this.firstElementChild);
    }
  }
};
customElements.define('site-card', cardElement);
[title] {
  background-color: #0F0;
  color: #000;
}
[body] {
  background-color: #F00;
  color: #000;
}
[actions] {
  background-color: #00F;
  color: #000;
}
<site-card>
  <section title>
    This is the title
  </section>
  <section body>
    This is the body
  </section>
  <section actions>
    <button class="modern small">Action</button>
    <button class="modern small">Action 2</button>
  </section>
</site-card>

I would suggest avoiding using innerHTML since that will wipe out any event handlers, etc. that might already exist. It may actually be slower depending on the number of direct children. It could also mess up any children that may be custom elements.

You should do it a bit later, in window.onload:

class cardElement extends HTMLElement {
    constructor() {
        super();
        var shadow = this.attachShadow({ mode: 'open' });
        var wrapper = document.createElement('div');
        wrapper.setAttribute('class', 'wrapper');
        window.onload = () => {
            wrapper.innerHTML = this.innerHTML;
        };
        var style = document.createElement('style');
        style.textContent = ... /* CSS removed to shorten. */
        shadow.appendChild(style);
        shadow.appendChild(wrapper);
    }
};
customElements.define('site-card', cardElement);

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742402849a4437259.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信