Custom Components
Getting Started
- Modalities
- Defining your Component
- Basic Component Structure
- HTML Template Syntax
- Managing State, Events, User Selection within Components
- Complete Carousel Example
- Troubleshooting Common Issues
Modalities
Touchpoint relies on modalities defined within the NLX application to send structured data from the NLX conversation flow to touchpoint. For each Modality defined in your conversational application that you wish to use with Touchpoint, you must create a component and explicitly enable that modality when creating your touchpoint instance.
Defining your Component
Each component should accept an object with
data
and conversationHandler
to access the conversation context sent from the NLX Application.
data
: Can be any type. It will match the schema set in the modality within NLX.conversationHandler
: The ConversationHandler. Functions to access the conversational context and send data back to NLX.
Add the Component to the
customModalities
configuration option paired with the name of Modality in NLX. In the example below the modality is named "MyComponentModality".
Basic Component Structure
Every custom component follows the same pattern. Here's a simple example in both JavaScript and HTML formats:
1<html lang="en"> 2 <head> 3 <title>Touchpoint Sample HTML</title> 4 <meta name="viewport" content="width=device-width, initial-scale=1"> 5 </head> 6 <body> 7 <script type="module"> 8 import { create, React, html } from "https://unpkg.com/@nlxai/touchpoint-ui@1.1.3/lib/index.js?module"; 9 10 const SimpleComponent = ({ data, conversationHandler }) => { 11 return html``; 12 }; 13 14 const touchpoint = await create({ 15 config: { 16 applicationUrl: "YOUR_APPLICATION_URL", 17 headers: { "nlx-api-key": "YOUR_API_KEY" }, 18 languageCode: "en-US", 19 }, 20 customModalities: { 21 SimpleModality: SimpleComponent, 22 }, 23 }); 24 25 </script> 26 </body> 27</html>
HTML Template Syntax
The
html
template literal tag allows you to create components without requiring JSX transpilation or build systems. This approach is powered by the htm library.
How the html
Template Tag Works
The
html
tag is a template literal function that:
- Parses HTML-like syntax at runtime
- Automatically imports all Touchpoint UI components
Accessing Components in HTML
When using HTML, always destructure the components you need from
nlxai.touchpointUi
:
HTML
1const { html, React, Icons } = nlxai.touchpointUi;
This gives you access to:
html
- The template tag for creating componentsReact
- React utilities like useStateIcons
- All available icon components- All other Touchpoint components (BaseText, CustomCard, etc.)
HTML vs JSX Quick Reference
Feature | JSX | HTML Template |
---|---|---|
Import | import { html } from "@nlxai/touchpoint-ui" | const { html } = nlxai.touchpointUi |
Component | <BaseText>Hello</BaseText> | html\ |
Props | label="Click me" | label="Click me" |
Dynamic Props | onClick={() => console.log()} | onClick=${() => console.log()} |
Key Differences from JSX
- No build step required
- Use
${}
for interpolation instead of{}
- Nested components require nested
html
templates - All Touchpoint components are automatically available
- Ideal for adding components to existing JavaScript codebases
Example Component in JSX and HTML
JavaScript
1import { React, BaseText, TextButton, Icons } from "@nlxai/touchpoint-ui"; 2 3const MyComponent = ({ data }) => ( 4 <> 5 <BaseText>{data.title}</BaseText> 6 <TextButton 7 label="Click me" 8 Icon={Icons.ArrowForward} 9 onClick={() => console.log("Clicked!")} 10 /> 11 </> 12);
HTML
1<script> 2 const MyComponent = ({ data }) => { 3 const { html, Icons } = nlxai.touchpointUi; 4 5 return html`12`; 13 }; 14</script>
Managing State, Events, User Selection within Components
Components often need to track state (like which item is selected) and handle user interactions (like clicks). Touchpoint provides React's state management and event handling patterns.
useState in Touchpoint Components
useState
returns an array with two elements:
- The current state value
- A function to update the state
When you call the update function, React will re-render the component with the new state value.
1<html lang="en"> 2 <head> 3 <title>Touchpoint Sample HTML</title> 4 <meta name="viewport" content="width=device-width, initial-scale=1"> 5 </head> 6 <body> 7 <script type="module"> 8 import { create, React, html } from "https://unpkg.com/@nlxai/touchpoint-ui@1.1.3/lib/index.js?module"; 9 10 const SelectableCard = ({ data, conversationHandler }) => { 11 // Declare state variable with initial value of false 12 const [isSelected, setIsSelected] = React.useState(false); 13 14 return html`31`; 32 }; 33 34 </script> 35 </body> 36</html>
Event Handler Pattern
Always use arrow functions for event handlers in both JavaScript and HTML:
1// Correct - arrow function 2onClick=${() => conversationHandler.sendChoice(data.id)} 3 4// Incorrect - immediate execution 5onClick=${conversationHandler.sendChoice(data.id)}
This ensures the function is called when the user clicks, not when the component renders.
Complete Carousel Example
Here's a complete carousel implementation following the standard pattern with CustomCardImageRow at the top and faded labels:
1<html lang="en"> 2 <head> 3 <title>Touchpoint Sample HTML</title> 4 <meta name="viewport" content="width=device-width, initial-scale=1"> 5 </head> 6 <body> 7 <script type="module"> 8 import { create, React, html } from "https://unpkg.com/@nlxai/touchpoint-ui@1.1.3/lib/index.js?module"; 9 10 const ItemsCarousel = ({ data, conversationHandler }) => { 11 // Track which item is selected 12 const [selectedItemId, setSelectedItemId] = React.useState(null); 13 14 return html`50`; 51 }; 52 53 // Register the component 54 const touchpoint = await create({ 55 config: { 56 applicationUrl: "YOUR_APPLICATION_URL", 57 headers: { "nlx-api-key": "YOUR_API_KEY" }, 58 languageCode: "en-US", 59 }, 60 customModalities: { 61 ItemsCarouselModality: ItemsCarousel, 62 }, 63 }); 64 65 </script> 66 </body> 67</html>
Troubleshooting Common Issues
HTML-Specific Issues
"nlxai is not defined"
- Cause: Script running before Touchpoint UI loads
- Solution: Ensure the script tag has
defer
attribute and wrap code incontentLoaded()
:
1<script 2 defer 3 src="https://unpkg.com/@nlxai/touchpoint-ui/lib/index.umd.js" 4></script> 5<script> 6 contentLoaded().then(() => { 7 // Your code here 8 }); 9</script>
Components not rendering
- Cause: Using JSX syntax instead of template syntax
- Solution: Use
${html
...}
for nested components:
1// Wrong 2left={<Carousel>...</Carousel>} 3 4// Correct 5left=${html`<Carousel>...</Carousel>`}
"React.useState is not a function"
- Cause: React not properly imported
- Solution: Destructure React from nlxai.touchpointUi:
1const { React } = nlxai.touchpointUi;
General Issues
Component receives undefined data
- Cause: Modality schema doesn't match expected data structure
- Solution: Log the data to check structure. See Subscribing to events for methods to check data outside components.
1<html lang="en"> 2 <head> 3 <title>Touchpoint Sample HTML</title> 4 <meta name="viewport" content="width=device-width, initial-scale=1"> 5 </head> 6 <body> 7 <script type="module"> 8 import { create, React, html } from "https://unpkg.com/@nlxai/touchpoint-ui@1.1.3/lib/index.js?module"; 9 10 const MyComponent = ({ data }) => { 11 console.log("Received data:", data); 12 // Component code 13 }; 14 15 </script> 16 </body> 17</html>
Choice not sent to NLX
- Cause: Missing or incorrect conversationHandler call
- Solution: Ensure you're calling the correct method. See Sending Messages and Data for more information.
1// For choices 2conversationHandler.sendChoice(choiceId); 3 4// For slots 5conversationHandler.sendSlots({ slotName: value });
React Version Mismatch Error
- Cause: Importing React from the parent project instead of from the touchpoint-ui package
- Solution: Import React directly from the
"@nlx/touchpoint-ui"
package when using JSX to build custom components. This ensures that the components will be running in the same React context as the Touchpoint UI using the correct version of React.
1// React is available as React in touchpointui 2const [state, setState] = React.useState(initialValue);