Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a DOM element in Stenciljs?

import { Component, Prop } from '@stencil/core';
@Component({
    tag: 'my-component',
    styleUrl: 'my-component.css',
    shadow: true
})
export class MyComponent {

  @Prop() first: string;
  @Prop() last: string;
  getElementHere() {
     // how can I get the div here?
  }
  render() {
    return (
      <div>
        Hello, World! I'm {this.first} {this.last}
      </div>
    );
  }
}

I want to get the DOM element just like in native JS. How do you do this in Stencil? getElementById does not work.

like image 548
SmallMan Avatar asked Apr 21 '18 07:04

SmallMan


People also ask

How do I create a component in Stenciljs?

Stencil components are created by adding a new file with a . tsx extension, such as my-first-component. tsx , and placing them in the src/components directory.

Does Stencil use virtual DOM?

One is a template syntax (JSX) and the other is a renderer (VDom). Stencil uses a much smaller and highly optimized VDom, but “how” the renderer works and improvements to be made are behind JSX.

Does Stenciljs use Webpack?

Stencil is a simple compiler for generating Web Components. The webpack plugin allows apps to easily import components using the webpack bundler. The plugin is for apps with build scripts already using a traditional webpack toolchain.

What is Host in Stenciljs?

<Host> is a virtual component, a virtual API exposed by stencil to declaratively set the attributes of the host element, it will never be rendered in the DOM, i.e. you will never see <Host> in Chrome Dev Tools for instance.


2 Answers

To expand on Fernando's answer, the @Element decorator binds the component's root element to this property. It's important to note a few properties of this approach:

  1. The @Element bound property is only available after the component has been loaded (componentDidLoad).
  2. Because the element is a standard HTMLElement, you can access elements within your current component using the standard .querySelector(...) or .querySelectorAll(...) methods to retrieve and manipulate them.

Here is an example showing when the element is accessible, and how to manipulate nodes within this element (correct as of stencil 0.7.24):

import { Component, Element } from '@stencil/core';

@Component({
    tag: 'my-component'
})
export class MyComponent {

    @Element() private element: HTMLElement;
    private data: string[];

    constructor() {
        this.data = ['one', 'two', 'three', 'four'];
        console.log(this.element); // outputs undefined
    }

    // child elements will only exist once the component has finished loading
    componentDidLoad() {
        console.log(this.element); // outputs HTMLElement <my-component ...

        // loop over NodeList as per https://css-tricks.com/snippets/javascript/loop-queryselectorall-matches/
        const list = this.element.querySelectorAll('li.my-list');
        [].forEach.call(list, li => li.style.color = 'red');
    }

    render() {
        return (
            <div class="my-component">
                <ul class="my-list">
                    { this.data.map(count => <li>{count}</li>)}
                </ul>
            </div>
        );
    }
}
like image 69
Squiggle Avatar answered Sep 17 '22 15:09

Squiggle


From the official docs

In cases where you need to get a direct reference to an element, like you would normally do with document.querySelector, you might want to use a ref in JSX.

So in your case:

import { Component, Prop } from '@stencil/core';
@Component({
    tag: 'my-component',
    styleUrl: 'my-component.css',
    shadow: true
})
export class MyComponent {

  @Prop() first: string;
  @Prop() last: string;

  divElement!: HTMLElement; // define a variable for html element

  getElementHere() {
    this.divElement  // this will refer to your <div> element
  }

  render() {
    return (
      <div ref={(el) => this.divElement= el as HTMLElement}> // add a ref here
        Hello, World! I'm {this.first} {this.last}
      </div>
    );
  }
}
like image 42
Manoj Negi Avatar answered Sep 20 '22 15:09

Manoj Negi