Skip to main content
Version: v5 (Preview)

Method Decorator

The @Method() decorator is used to expose methods on the public API. Functions decorated with the @Method() decorator can be called directly from the element, i.e. they are intended to be callable from the outside!

import { Method } from '@stencil/core';

export class TodoList {

@Method()
async showPrompt() {
// show a prompt
}
}

Call the method like this:

note

Developers should ensure that the component is defined by using the whenDefined method of the custom element registry before attempting to call public methods.

(async () => {
await customElements.whenDefined('todo-list');
const todoListElement = document.querySelector('todo-list');
await todoListElement.showPrompt();
})();

In this playground, the button in index.html calls showPrompt():

index.html
<script type="module" src="./todo-list.js"></script>

<button>Add a todo</button>
<todo-list></todo-list>

<script>
document.querySelector('button').addEventListener('click', async () => {
await customElements.whenDefined('todo-list');
const todoListElement = document.querySelector('todo-list');
await todoListElement.showPrompt();
});
</script>
todo-list.tsx
import { Component, Method, State } from '@stencil/core';

@Component({ tag: 'todo-list' })
export class TodoList {
@State() prompting = false;

@Method()
async showPrompt() {
this.prompting = true;
}

render() {
return this.prompting ? <input placeholder="What needs doing?" /> : <p>No prompt yet</p>;
}
}

Public methods must be async​

Stencil's architecture is async at all levels which allows for many performance benefits and ease of use. By ensuring publicly exposed methods using the @Method decorator return a promise:

  • Developers can call methods before the implementation was downloaded without componentOnReady(), which queues the method calls and resolves after the component has finished loading.

  • Interaction with the component is the same whether it still needs to be lazy-loaded, or is already fully hydrated.

  • By keeping a component's public API async, apps could move the components transparently to Web Worker and the API would still be the same.

  • Returning a promise is only required for publicly exposed methods which have the @Method decorator. All other component methods are private to the component and are not required to be async.

// VALID: using async
@Method()
async myMethod() {
return 42;
}

// VALID: using Promise.resolve()
@Method()
myMethod2() {
return Promise.resolve(42);
}

// VALID: even if it returns nothing, it needs to be async
@Method()
async myMethod3() {
console.log(42);
}

// INVALID
@Method()
notOk() {
return 42;
}

Private methods​

Non-public methods can still be used to organize the business logic of your component and they do NOT have to return a Promise.

class Component {
// Since `getData` is not a public method exposed with @Method
// it does not need to be async
getData() {
return this.someData;
}
render() {
return (
<div>{this.getData()}</div>
);
}
}