What is the best way to assign multiple event handlers to Solid.js components within a single HTML element?

Introduction

I am currently exploring Solid.js and facing a challenge in adding multiple event handlers to the same HTML element from different components using JSX. While it's straightforward in Vue, I have noticed that Solid.js overrides events based on how they are added. I have demonstrated this behavior in both frameworks in an example which you can access here. In Vue, adding multiple event handlers works as expected, but in Solid, any additional event handler seems to override the previous one for a single event.

If you want to compare behaviors, you can toggle between useDivAsComponent in Solid and useDivAsComponent in Vue. Vue consistently handles multiple event handlers attached to a component or HTML element, while Solid's behavior varies depending on where events are added - either to an HTML element or another component.

My question is whether there is a simple way to attach multiple event handlers to the same HTML element using different components defined with JSX in Solid?

Details

In a scenario where I need to add DOM event handlers to the root element of a component, I also want users of the component to be able to append their own DOM event handlers to it. If the root element is like

(props) => <div {...props} />
, only the internal event handlers within the component are effective (external ones will be overruled). This happens because Solid merges props, resulting in only the last event handler being retained instead of utilizing addEventListener.

However, if the component's root element is a standard <div />, Solid generates code in a way that preserves both sets of event handlers. The built code shows Solid using addEventListener(), which aligns with expectations.

Potential Solutions

To work around this issue, one approach could involve passing a reference to the inner component (

<InnerComponent ref={ref} />
) to the parent and manually adding event listeners to prevent additional events from getting overridden (ref.addEventListener(...)). Although effective, this method may not be as user-friendly compared to other frameworks.

Alternatively, ensuring that the inner component where event handlers are applied is a regular <div /> may prompt Solid's compiler to generate code that incorporates event listeners instead of merging (and replacing) event handler props.

I am eager to discover a more seamless way to include multiple events in JSX, if feasible.

Answer №1

If you're looking to prevent overwriting events in Solid-js, consider using onmouseleave (in lowercase). This approach will not overwrite existing events but instead "sum" them together since Solid-js interprets lowercase as adding a new event listener. You can find more information about this discussion Here.

In your solid-js example, the implementation would look something like this:

import { render } from 'solid-js/web';
import { Component, JSX } from "solid-js"
type HtmlProps = JSX.HTMLAttributes<HTMLDivElement>

const useDivAsComponent = true

const ComponentInner: Component<HtmlProps> = (props) => {
  const log = (name: string) => console.log("inner", name)
  const Div = (p: HtmlProps) => <div {...p} />
  return useDivAsComponent
     // onmouseenter, onmouseleave, instead of onMouseLeave onMouseEnter
    ? <Div {...props} onmouseenter={[log, "enter"]} onmouseleave={[log, "leave"]} />
    : <div {...props} onmouseenter={[log, "enter"]} onmouseleave={[log, "leave"]} />
}

const ComponentOuter: Component<HtmlProps> = (p) => {
  const log = (name: string) => console.log("outer", name)
  return <ComponentInner {...p} onMouseEnter={[log, "enter"]} onMouseLeave={[log, "leave"]} />
}

const style: JSX.CSSProperties = { background: "lightgrey", width: "100%", height: "100vh" }
render(
  () => <ComponentOuter style={style} class='hola'></ComponentOuter>,
  document.getElementById('app') as HTMLElement
)

This modification should address your concerns. Best of luck!

Answer №2

In the Solid framework, there are several methods for adding event listeners. Event listeners added as a prop, like onClick, are delegated, meaning they are attached to the document node for improved performance. For non-delegated handlers, you can use the syntax on:{eventName}.

If you need to add a listener to an element within another component, using refs is recommended. This marks the third method, in which you can utilize addEventListener.

The approach you are currently employing is not optimal. A better strategy would be to have a single, delegated listener on a common ancestor, and then use conditionals inside the handler's body.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering issues with browser tabs and Socket.IO

I'm currently working on a real-time chat using Socket.IO, but I've encountered a major issue. The aim is to allow users to log in, select another connected user, and start chatting... var http = require('http'), fs = require(&ap ...

Error in Next.js 13 due to Prisma table mapping causing hydration issues

I recently created a basic project in Next.js 13 and encountered a Hydration Error even though my project is not doing much. The code snippet below seems to be the cause of the issue: import { PrismaClient } from "@prisma/client"; export default ...

Exploring the functionality of placeholders within jQuery

I am trying to create a customizable text template where I can insert placeholders and then fill those placeholders with data to use on my page. For example: var template = '<div class="persons">'; template += '<p> <span clas ...

Discover the best methods for accessing all pages on a Facebook account

I attempted to retrieve a list of all Facebook pages, but encountered an error. The error message states: 'request is not defined.' Here is the code snippet: var url = 'https://graph.facebook.com/me/accounts'; var accessToken = req.u ...

Get the hash value after a specific character using Javascript

I'm currently working on a website with ajax functionality where pages load when clicking on navigation buttons. However, I encounter issues when reloading the page as it defaults back to loading main.html, regardless of the URL. The hash being used i ...

SQL inputs with information that updates automatically / autofill SQL input boxes

Is it feasible to create a webpage that can connect to an SQL database, retrieve information from a table, and display it in a text box based on the input provided in another text box? Essentially, I am looking for a way to enable autofill functionality. I ...

Dnd-kit: item loses its place in line when dragged over Droppable area

I've encountered an issue while using @dnd-kit. The sorting function works smoothly (e.g. when I drag the 1st element, it sorts correctly), but once I reach a droppable element (green Thrash), the sorting breaks and the 1st element snaps back. You ca ...

Add a fading transition feature to images that are loaded at a later time

I used a clever technique to create a blur effect by loading a small, lightweight image first. Once the main background image is loaded, it swaps out the 'data-src' with the actual image. However, I am facing an issue with the abrupt transition, ...

Activate the element only when all input fields are completed. This function can be used repeatedly

I am working on developing a versatile function that will iterate through all input fields. If any of these fields are empty, I want to trigger the toggling of a class name (disabled) on another element (such as an anchor or button). Currently, the functi ...

Is there a way to restore a previous version of package-lock.json?

Currently, I am facing the challenge of adjusting a JS/node project that includes a package.json but lacks a committed package-lock.json file. Additionally, the original package-lock.json from the author is not available as newer versions have been develop ...

What causes the issue of the 'MERGE' statement in Node.js resulting in the creation of duplicate nodes in Neo4j?

Currently tackling a Node.js project involving the creation of nodes in Neo4j using the 'MERGE' statement. Despite employing 'MERGE' to prevent duplicate nodes, duplicates are still being generated at times. Extensive searches through ...

Why is it that the HttpClient constructor in Angular doesn't require parameters when instantiated through the constructor of another class, but does when instantiated via the 'new' keyword?

I am trying to create a static method for instantiating an object of a class, but I have encountered a problem. import { HttpClient } from '@angular/common/http'; export MyClass { // Case 1 public static init(): MyClass { return this(new ...

What are some ways to implement smooth scrolling when a navigation link is clicked?

I have a total of 3 links in my navigation bar and every time they are clicked, I want the page to smoothly scroll down to their designated section on the webpage. Although I have already set up the anchors, I lack experience in scripting to create the smo ...

Looking to display a single Angular component with varying data? I have a component in Angular that dynamically renders content based on the specific URL path

I have a component that dynamically renders data based on the URL '/lp/:pageId'. The :pageId parameter is used to fetch data from the server in the ngOnInit() lifecycle hook. ngOnInit(){ this.apiHelper.getData(this.route.snapshot.params.pageId) ...

Using JavaScript to display content on the page after handling a form

Hey there! I'm currently working on a website project where users can input their name and have it displayed on the page. My plan is to achieve this using JavaScript. HTML: <div id='errormsg'></div> <form action='' ...

Struggles encountered while configuring React

I'm in need of assistance with setting up React, even though I have both Node and npm installed. When I enter the following command: npx create-react-app new-test-react --use-npm I encounter the following error message: npm ERR! code ENOTFOUND npm E ...

All menus effortlessly sliding out simultaneously

I'm having an issue with my navigation bar. I want each link to slide its corresponding DIV up or down when clicked. However, all the DIVs are sliding and when clicking on the same link everything slides up. How can I fix this problem? This is my HT ...

Is there a way to generate a modal list of values by utilizing bootstrap and angular, while incorporating spring boot as the backend technology?

I'm working on developing a generic "List of Values" feature, which will be a searchable modal containing a natural identifier and description. I have successfully built an AngularJS application in Spring Boot to accomplish this task, but unfortunatel ...

Function for masking phone numbers is adding additional "x's" to the input field

My phone number formatting script is supposed to add dashes after the third and sixth characters, as well as insert an "x" after the 10th character for extensions. However, it is adding extra "x's" after the 12th character, resulting in the incorrect ...

Exploring the functionality of routes with the identifier :id

Is there a way to test routes with :id parameters included in them? Let's consider an example where we have a route like this: Router.get('/:id/profile I came across a scenario in someone else's code where they passed a string of numbers ...