This feature is experimental within the Stencil Library (Docs) and is automated within their build process. Please report any issues encountered. However, note that the Tecton team does not maintain this specific tool.
This tutorial assumes your codebase is registering the Web Components via connect
from the q2-tecton-sdk
, or from the q2-design-system
library (Guide).
If you're using React to build out your feature or application, then you can make use of the React component wrappers that are published as a part of Tecton.
This gives you a number of benefits including:
refs
for adding event listeners to Web ComponentsMaking use of the React component wrappers only requires a couple of steps.
First, you will need to install the framework wrappers library:
npm i q2-tecton-framework-wrappers
yarn add q2-tecton-framework-wrappers
Once the package is installed you can start using the components by importing the ones you need, just like you would with any other components. They are all located in q2-tecton-framework-wrappers/dist/react
.
import { Q2Btn, Q2Input, Q2Section } from "q2-tecton-framework-wrappers/dist/react";
function Example() {
const onFullNameInput = (event) => {
const {
detail: { value },
} = event.nativeEvent;
console.log(value);
};
return (
<Q2Section label="My Section" collapsible expanded>
<Q2Input label="Full name" optional onInput={onFullNameInput}></Q2Input>
<Q2Btn intent="workflow-primary">Submit</Q2Btn>
</Q2Section>
);
}
export default Example;
React currently faces a few challenges when dealing with Web Component attributes/properties and events. While React component wrappers have addressed the property-related issues, event-related issues persist. This primarily results from React's employment of synthetic events (Docs) for standard event names such as "change"
and "input"
(See a full list on MDN). As a result, setting up event listeners in your JSX with properties like onInput
or onChange
may not function as anticipated.
The React team is actively working on this issue and has provided a solution in their experimental branch, although it is not yet widely available.
In the interim, we suggest utilizing one of the two following workarounds:
This method, although somewhat awkward, is effective for all event types. It involves the following steps:
useRef
.useEffect
hook, use the ref to add your desired event listener(s) to the element.useEffect
hook's return function, ensure that the event listener(s) are removed when the component is destroyed.Here is a complete, functional example that demonstrates this approach:
import { Q2Input } from "q2-tecton-framework-wrappers/dist/react";
import { useEffect, useRef } from "react";
function MyComponent() {
const inputRef = useRef<HTMLQ2InputElement>(null);
useEffect(() => {
const input = inputRef.current!;
const onInput = (event: Event) => {
const newEvent = event as CustomEvent;
console.log("onInput", newEvent.detail);
};
input.addEventListener("input", onInput);
return () => {
input.removeEventListener("input", onInput);
};
}, []);
return <Q2Input ref={inputRef} label="Name" />;
}
export default MyComponent;
React's Synthetic Events are defined solely for native events (like input
, change
, and so on). Because React employs camel-case naming for its Synthetic Event listeners, you can bypass the problem by using original lowercase event listener attributes.
While this is a more straightforward solution, your linter may flag your use of lowercase attributes in React, hence the use of @ts-ignore
in the example provided.
Additionally, if you're adding an event listener for a non-native event name, use the standard camel case format you're accustomed to in React (e.g., onClear
in the example below).
Here is what that would look like:
import { Q2Input } from "q2-tecton-framework-wrappers/dist/react";
function MyComponent() {
return (
<Q2Input
label="Name"
// @ts-ignore
oninput={(event: CustomEvent) => {
console.log("oninput", event.detail.value);
}}
onClear={(event: CustomEvent) => {
console.log("onClear", event.detail.value);
}}
/>
);
}
export default MyComponent;
We apologize for any inconvenience this situation might cause and look forward to an upcoming release from the React team to address this issue.