Handling Events for Multiple Elements

Okay we have a very useful video on this. Thank you. I want to use this video as a foundational form for a “like” / “unlike” button icon. This would allow a user client to create a list of favorited items to look at in their account. The video shows how to capture the item clicked (to limit the number of event listeners). All good. But is there a way to be sure that the data passed to a DB in an API call is IN FACT synced with what’s on the client’s page. What if there is a 400 type error in the API call? Is it necessary to loop through all the items on the page after clicking on the item to find the one that was click originally? Or is there a more elegant way to find the item to sync the DB table record with the item on the web page. Is that overkill? I.e. not necessary?

Hi @david78737 - welcome to the forums :slight_smile:

The event handling code described will give you the exact item that the user clicked on. I’m assuming that the item would either be a Like or Unlike button. If that is the case, let me summarize your question to ensure I understand it.

You want to ensure that when you react to the Like or Unlike event, that it matches what the database state is. For example, a user could have clicked “Like”, but some API errors on route to the database could cause the database to not store the correct state. At this point, the UI on the page would indicate “Like”, but the database would have no record of it - creating an inconsistency. How can you detect this inconsistency and stop it?

If I summarized your question correctly, what you can do is double check that sending the API request results in an OK/200 status. If you don’t hear back on that status, you can ensure the UI state goes back to a point where no Like or Unlike action had taken place. I would also suggest prompting the user with a message to indicate that the action failed and they should try again provided we can’t automatically retry and make the request succeed.

Doing all of this wouldn’t require you to loop through all items on the page and double check with the database.

Does this help?

Yeah that helps a lot. I appreciate your clarity in the video. Nice. I have prototyped this and it is working on the page. I can change a class and create a JSON object in the code. But when it came to sending the JSON payload to the API (Xano) database back end I did run into a challenge - a 404 error.

I’m working with Webflow as a front end. That does present challenges form time to time just to work withing their interface. But it’s not clear to me that is the problem. I’m getting a 404 error when clicking an the element - the “like / unlike” button: TypeError: Constructor ArrayBuffer requires ‘new’.

.

I’m using dummy hard coded values in the code during this testing phase. I’m not getting any errors in the JS loading the page. Just when I click on the gray heart icon to “like” the item. I know the API works as expected but I’m not sure the API is coded properly.

Regards
DAvid

When you copy/paste the URL from the error (https://x8ki…) into the address bar, do you still see a 404 error?

Yeah, I get a 404 error
favorites 404 error 03
The API from Xano looks like this:
https://x8ki-letl-twmt.n7.xano.io/api:arLEd2EP/update_favorites/{data}” without the quotes where the {data} is JSON.
I’ve not had the opportunity to build a POST http request before so I don’t know what to expect. I’ve handled form submissions from Webflow but that’s not the same thing.
When running this in the Xano API builder it works fine. It could be I need to build it again - the URL might be corrupted.

I’ve successfully worked through the code to change the like button (icon, really) but I am receiving an error where the click event target is “undefined”. This is at this statement in the code:
if(e.target !== e.currentTarget){
The error:
TypeError: Cannot read properties of undefined (reading ‘target’)

I found a reference that distinguishes between e.target and e.currentTarget that seems relevant to my error but I do not find a way to remedy the error. I should mention that I am NOT using a link with an href with the icon to trigger the function call. Instead I am using CSS cursor:pointer to trigger the click event and it applies to a div with an unique id =‘aidxxxx’ and class=‘likebutton’.

The click handler is added with this statement as each image is created for the page and references the unique id of the image database. updateFav() is a function that changes the class and initiates the API call.
$(clone).find(’#’ + likeButtonID).click(function() {
updateFav();
});

Given the function you posted for listening to the click event, that makes sense, for there is no object called “e” in this context. Do you have access to an event object where if you typed event.target and event.currentTarget, the property is properly associated with an object?

This may require you to modify your click function’s arguments to actually pass in the event between both function(event) and updateFav(event).

:slight_smile:

This is over my head. I figured there was an object somewhere in all that code but I haven’t learned about event objects yet.

What is the “event object” in the code in your video. I used your “theDude” name and the click handler same as the video:.
var theParent = document.querySelector(“#theDude”);
theParent.addEventListener(“click”, updateFav, false);

I loop through the pattern below to clone each image and append the clone to a grid. The grid contains all the images and the corresponding like buttons. The grid lives inside ‘theDude’ div. The like icon is constructed like this:

  1. const myLikeButton = $(“#aid”); // the “pattern to clone” is a div with an id and a class
  2. const myClone = $(myLikeButton).clone(); // IS THIS THE e.target?
  3. // the element ID is used as a UUID and id for button element
  4. const myCloneID = “aid” + artworkID; // e.g. aid123456
  5. //update button element ID
  6. $(clone).find(‘#aid’).prop(“id”, myCloneID );
  7. // remove all class name(s) to remove any Webflow modifications
  8. $(clone).find(‘#’ + likeButtonID).removeClass();
  9. // add the needed class names
  10. $(clone).find(‘#’ + likeButtonID).addClass(“likebutton false”);
  11. //create click function that triggers updateFav function
  12. $(clone).find(‘#’ + likeButtonID).click(function() {
  13. updateFav();
  14. });

It is probable that I’m missing something to contain the event object. I thought it would be the div element with the unique ID that receives the click function in statement 12. But should it be ‘myClone’ in statement 2?

Yes, events are a different best altogether. I suggest first looking into this tutorial that covers events and also the event object:

That may help you better understand where we need to make adjustments, for I think you are close!

Hi there

Thank you for the video reference. I learned a lot and have a better understanding of event and the event (‘e’ object).

I am still coming up with the same errors. The error might suggest that the browser is not picking up the value or any value from the item clicked. But the alert displays the id of the heart icon as expected. What is confusing is this “type error” where “Cannot read properties of undefined (reading ‘target’)”.

Clearly the event captured something - in fact did capture the id ( ‘aid21’ ) of the element containing the heart icon which is an empty div. Does this functionality require more than an empty div to have readable properties? I’d be happy to accommodate if I knew what to do…

Here is the JavaScript of the relevant code. So ‘target’ here is a property?

What does event target refer to?
target , is a property of an event which is a reference to the element upon which the event was fired. The HTML: a div with an id and a class. The class is a compound class showing the gray heart or the red heart. Is more needed?

Target is a property that points to the element that fired the event. Based on what you’ve just shown in the screenshot, your code seems to be working correctly where you are seeing the correct id value. Right?

Hey mate,

A DOM node, much like an event… is an object in Javascript.

e.target is a pointer to the actual DOM node in the document…

  • if you console.log(e.target) you will log the DOM node (object) that was clicked and all of its properties e.g. id, class, innerHTML, outerHTML ect…
    NOT the event object

  • if you console.log(e.target.id) you are accessing the id property of the DOM node e.g <div id = “aid21” class = "class1 class2" >THIS IS A DIV !</div>
    will log "aid21"

  • OR if you console.log(event.target.innerHTML) you will log "THIS IS A DIV!"

If you are using event propagation I would recommend:

  • set all elements in your CSS as *{pointer-events: none}

  • create a class “clickable” that you attach to every button input ect
    e.g .clickable{pointer-events: auto} or button, input, select{pointer-events: auto}

  • set your events as a data-set attribute to the DOM node e.g.
    <div data-event = ‘open_modal’ class = "class1 class2" >THIS IS A DIV !</div>

  • access the event like e.target.dataset.event ("open_modal")

  • run the event as a property of an object e.g.

const events = {
    no_event: function(){return console.log("no event attached")},
    open_modal: function(e){
      // run some code
    }
}
const listenHandler = function(e){
  if(e.target === e.currentTarget) return
  let run = events[e.target.dataset.event] || events["no_event"];
  return run(e)
}
  • have a fallback value for when you have forgotten to add an attribute to the element as above

There’s probably a few similar approaches that do the same thing :slightly_smiling_face:

1 Like

Jynx!.. :laughing:

1 Like

Kirupa
It appears I have this sorted. I was adding a click handler to an element that already had a click handler. I sorted out some JavaScript / jquery methods as well. The CSS cursor:pointer I applied to the likebutton class apparently made it clickable. I did some sleuthing and found I was clicking on {Object object} so went back through your coding.
So in my situation where I was cloning a set of elements, the CSS solution was effective contrasted with adding a click handler to each button element.
Additionally analysis demonstrated I was cloning an element that was already cloned.

This stuff gets deep very quickly

I want to express gratitude to Steve Mills and you taking a look at this.

The page is working but still not updating the database yet. That is less of a challenge.

2 Likes

Glad we could help, and keep at it! You are on the right path here :slight_smile:

1 Like