It's much easier to help with this with the source (rather than the output) link at https://stackblitz.com/edit/mjmihk
First of all:
var elem: any = document.querySelector("simple-greeting");
Gets the first instance of this component in the document
, so will fail if you have more than one. You don't need this, as any event subscribed with Lit's @
syntax will be called with this
as the current element.
That means your next line should be:
const cpRoot = this.shadowRoot.querySelector("#cproot");
However, there's a better way again to get that using LitElement's @query
decorator:
@query('#cproot') private cpRoot: HTMLDivElement;
_handlePrintClick() {
console.log("copy/paste/print content:", this.cpRoot.innerHTML);
}
Your next problem is innerHTML
- this gets the light DOM. With web components you now have two types of document - the HTML you put inside the component, and a new isolated HTML that component owns.
For instance, if you had:
<child-greeting name="Peter">
#shadow-root [<p>I am the child. ...!</p>]
<p>Something else about Peter</p>
</child-greeting>
(And child-greeting
had a <slot>
) then innerHTML
will give you <p>Something about Peter</p>
, which is the light DOM. Your shadow DOM (the <p>I am the child. ...!</p>
bit) isn't included.
For most custom elements this is exactly what you want, as the shadow DOM will hold the component part - the dropdown on a select or date picker, the action buttons on a rich text input, etc. Many browsers use then internally - for instance <video>
has shadow DOM that renders the play button, progress bar, etc.
You have two options:
- Break shadow DOM on elements you want to expose their content to
innerHTML
. You can do this with LitElement by overriding the method that creates the shadow DOM fragment to return the control instead:
createRenderRoot() {
return this;
}
- Access the DOM directly rather than using
innerHTML
. This would require recursion down the tree checking for shadowRoot
on every element, and any that used <slot>
will have to have their DOM tree rebuilt to put nested light DOM content into it.
Neither of these is particularly easy, and both have compromises.