Tips for triggering an event from a function instead of the window

Everything is functioning as expected, with the event listener successfully capturing the custom event when it is dispatched from the window and listened for as loading, all seems to be working well.

const MyLib = mylib();
  function mylib() {
    const res = {
      init: (data) => {
        let loading = new CustomEvent('loading', {detail: { loading: true }});
        window.dispatchEvent(loading);
      }
    }
  return res;
}

event listener

 window.addEventListener('loading', handleLoading);

I'm looking to update it to use MyLib.addEventListener instead of window.addEventListener.

Additionally,

window.dispatchEvent(loading); should become MyLib.dispatchEvent(loading);

However, when attempting this change, I encounter an error message stating

TypeError: MyLib.addEventListener is not a function

The solution posted below involves using a class, but I am curious if it is possible to achieve this without utilizing a class structure.

Answer №1

To effectively handle events on an object, the object must inherit from the EventTarget interface.

class MyLibrary extends EventTarget {
    constructor() {
        super();
    }

    initialize(data) {
        let loadingEvent = new CustomEvent('loading', { detail: { loading: true } });
        this.dispatchEvent(loadingEvent);
    }
}

// Assume myLibrary is an instance of MyLibrary

useEffect(() => {
    myLibrary.addEventListener('loading', handleLoading);
    return () => {
        myLibrary.removeEventListener('loading', handleLoading);
    };
}, []);

Answer №2

Using a Proxy object can help meet the specifications.

This code snippet demonstrates how the original MyLib object is encapsulated within a Proxy. The get trap of the Proxy is triggered when accessing methods like addEventListener or dispatchEvent.

function mylib() {
  const res = {
    init: (data) => {
      let loading = new CustomEvent('loading', {detail: { loading: true }});
      MyLib.dispatchEvent(loading);
    }
  }
  return res;
}

const MyLib = new Proxy(mylib(), {
  get: function(target, prop) {
    if (prop === `addEventListener`) {
      return (...args) => window.addEventListener(...args);
    } 
    if (prop === `dispatchEvent`) {
      return (...args) => window.dispatchEvent(...args);
    }
    return target[prop];
  }
});

MyLib.addEventListener('loading', () => { console.log("Hello world !!!") });
MyLib.init();

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

While it is possible to filter by friend.brand.id within friends in Angular, unfortunately the || undefined trick cannot be used to reset the filter when it is NULL

In the futuristic world of 2075, immortal humans have subjugated mortal humans. There exists a unique store where mortal friends are sold, and efforts are being made to develop an app that allows customers to manage their friends based on their favorite br ...

Arranging a string array in JavaScript according to an integer array

Looking at the provided javascript arrays: letterArray ['a', 'e', 'i', 'o', 'u'] We also have another array that corresponds to it: valueArray [12, 22, 7, 7, 3] The goal is to sort the valueArray into: ...

Declarations of Typescript React for Props for Specific Element

I am trying to specify types for certain elements like <button> or <input>, but I am unable to differentiate between specific element types. Here is an example: interface Props{ component: React.ComponentProps<"button"> | nev ...

What is the best way for library creators to indicate to VSCode which suggested "import" is the correct one?

As a library creator, I have noticed that VSCode often suggests incorrect imports to users. For instance, VSCode typically suggests the following import: import useTranslation from 'next-translate/lib/esm/useTranslation' However, the correct im ...

Using Rails to render a partial containing a form object

I need help with rendering a partial called 'colordata' after selecting a color from a dropdown list using Ajax. Unfortunately, I'm not seeing any changes on the main page and the form is undefined in the colordata partial. This is the sche ...

Should the header include individual CSS and JS files, or should all code be contained within a single CSS and JS file?

As I work on optimizing my website, I find myself juggling multiple plugins that include jQuery plugins with CSS along with my own JavaScript code. Currently, the CSS is spread across separate files for each plugin I have downloaded. When needed on a page ...

What are the steps to integrate the vue-tweet-embed node package into vuejs2?

I am having trouble figuring out how to implement the vue-tweet-embed plugin in my Vue file. I keep getting an error message that says: Unknown custom element: - have you properly registered the component? If dealing with recursive components, ensure ...

Error: Unable to access the property 'map' as it is undefined | React, Redux

I'm encountering an issue that says: TypeError: Cannot read property 'map' of undefined. This error is related to trying to map over the array (posts) when it's empty: const postsList = posts.map((postList, i) => { Here is my actio ...

Is it possible to execute "green arrow" unit tests directly with Mocha in IntelliJ IDEA, even when Karma and Mocha are both installed?

My unit tests are set up using Karma and Mocha. The reason I use Karma is because some of the functionality being tested requires a web browser, even if it's just a fake headless one. However, most of my code can be run in either a browser or Node.js. ...

Webpack focuses solely on serving HTML files, neglecting to deliver the underlying code

Hey there! I'm currently working on a project that involves using React, TypeScript, and Webpack. I ran into some errors previously that prevented the code from compiling, but now that's fixed. However, when I run webpack, it only serves the HTML ...

Processing images with PHP from an array using AJAX

I have designed a straightforward form for image uploading. I am storing the properties of the uploaded images in an array, and my goal is to send this array to a PHP file using ajax. However, when I attempt to access the uploaded image using $_FILES[&apos ...

Insert HTML content into an iframe with a callback function

We are receiving information from the backend server and need to transfer it to an iframe. In order to accurately set the height of the iframe to match the content, we must wait for the content to be loaded into the iframe. However, this process may not ha ...

React Material-UI - Mobile-friendly Masonry Layout

I'm new to working with React and I'm currently exploring how to create a Masonry image grid that is responsive for mobile devices. The goal is to have the images stack on top of each other in mobile view while maintaining the classic Masonry gri ...

Incorporate a class into the fixed navigation menu using fullpage.js

I am attempting to modify the behavior of a sticky menu as the user scrolls down using fullpage.js. My goal is to have the #top-wrapper behave normally when the first section/page loads, and then add a class of is-fixed as you scroll down. When scrolling ...

Tips on organizing a JSON object for a JavaScript project

For my project, I am designing a data structure that utilizes JSON. My goal is to create an efficient method for searching and editing the JSON object. Which structure would be considered standard in this scenario? Is there a preferred way to implement eit ...

Next.js does not recognize Typescript Context

I encountered an unexpected custom error while trying to implement custom error notifications in my form. The custom context I set up for this functionality does not seem to be working as intended, resulting in a thrown error for its non-existence. My deve ...

Is there a way to assign the chosen option from a dropdown list to an input field in Vue 3?

I am working with a list that is returned from an API request. I have a text input field where I can search for items in the list, and the results are displayed dynamically as I type. My goal is to be able to select an option from the list and display the ...

If a generic string argument is not specified as a string literal, it will not be narrowed unless it is the first argument

When the following code is executed, it works as intended and we can see that the arg variable is a string literal: const foo = <T extends string = string>(arg: T) => {}; foo('my string'); // const foo: <"my string">(arg ...

Button Click Not Allowing Webpage Scroll

I am currently in the process of developing a website that aims to incorporate a significant amount of motion and interactivity. The concept I have devised involves a scenario where clicking on a button from the "main menu" will trigger a horizontal and ve ...

Adding a property conditionally in jsx: A guide

I have a simple example of Material UI RadioGroup code that I want to display conditionally in either a row or column format. By default, it is displayed in column format. Below is the code snippet: <RadioGroup aria-label="gender" name=&q ...