Adding event listeners to modal buttons in a Handlebars template is a simple process that involves utilizing the `

I've been working on developing a web application that interacts with a news API to display articles. Each article is presented in a card format, and I have also incorporated modals using handlebars.

My goal is for each card's button to trigger the opening of a modal containing unique information related to that specific article.

I'm currently facing an issue where clicking the button on the card does not open the corresponding modal, nor does it generate any error messages.

I suspect that there might be an issue with how the script is interpreting the button's class, denoted as {{@index}}.

<div class="">

  
    {{!-- #each article --}}

    <div class="row">

        {{#each articles}}
        
        <div class="col-12-sm col-6-md col-3-lg">
            <div class="card m-2">
                <div class="card-body">
                <h5 class="card-title">{{title}}</h5>
                <p class="card-text">{{description}}</p>
                </div>
                <img class="card-image" src="{{urlToImage}}" alt="Card image cap">
                <button id="mybtn" class="{{@index}}">Open Modal</button>
                            
            </div>
        </div>

        {{/each}}

    </div>
</div>


{{#each articles}}

        <!-- The Modal -->
        <div id="modid" class="modal">

            <!-- Modal content -->
            <div class="modal-content">
                <span class="close">&times;</span>
                <p>Some text in the Modal..</p>
            </div>
        </div>

{{/each}}


<script>

    
    let modal = document.getElementById("modid");

    let btn = document.getElementById("mybtn");

    let span = document.getElementsByClassName("close")[0];

    btn.onclick = function() {
        modal.style.display = "block";
    }

    span.onclick = function() {
            modal.style.display = "none";
    }

    window.onclick = function(event) {
        if (event.target == modal) {
                modal.style.display = "none";
        }
    }

    const btn = document.querySelector('.{{@index}}');
    btn.addEventListener('click', function(event){
        console.log('Button Clicked');
    }

        
</script>

If you have any insights or advice on how to resolve this issue, I would greatly appreciate your input!

Answer №1

Initially, I suggest using a data-attribute like

data-open-modal="{{@index}}"
instead of class="{{@index}} for each button. This approach allows easy access to all open modal buttons and specific index values in the click handler.

Furthermore, assigning a single id, such as id="modid", to multiple modal elements is incorrect HTML practice. It's best to eliminate this id attribute to avoid confusion and specify the target modal clearly.

In the JavaScript section, select and store all open modal buttons and modals in variables:

const openModalButtons = document.querySelectorAll('[data-open-modal]');
const modals = document.querySelectorAll('.modal');

Iterate through each openModalButtons and attach a click event handler to them:

openModalButtons.forEach(openModalButton => {
  openModalButton.addEventListener('click', (event) => {
    const openIndex = Number(event.target.dataset.openModal);
    
    modals.forEach((modal, index) => {
      modal.classList.toggle('open', index === openIndex);
      modal.classList.toggle('closed', index !== openIndex)
    });
  });
});

Note that the click handler retrieves the index value from the clicked button's data-open-modal attribute, guiding which modal to display.

Then, it loops over each modal element setting the "open" class if the index matches the desired modal, or the "closed" class otherwise.

I have provided a handy reference fiddle.

Update: To handle closing functionality:

The close button can be handled similarly to the open button by attaching an event listener and utilizing a data-attribute:

<button class="close" data-close-modal="{{@index}}">&times;</button>
. Remember, a close button should ideally be a <button rather than a <span>.

The event listener for close buttons closely resembles that of open buttons. Instead of looping through all modals, it targets the modal matching the data-close-modal attribute value of the clicked button.

const closeModalButtons = document.querySelectorAll('[data-close-modal]');

closeModalButtons.forEach(closeModalButton => {
  closeModalButton.addEventListener('click', (event) => {
    const closeIndex = Number(event.target.dataset.closeModal);
    
    modals[closeIndex].classList.remove('open');
    modals[closeIndex].classList.add('closed');
  });
});

Note: Depending on your needs, you may only need either an .open or a .closed class for your modals - one may suffice. The current setup is just an example.

An updated version of the fiddle is available here.

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

Looping through each combination of elements in a Map

I have a Map containing Shape objects with unique IDs assigned as keys. My goal is to loop through every pair of Shapes in the Map, ensuring that each pair is only processed once. While I am aware of options like forEach or for..of for looping, I'm s ...

Tips for interpreting information from a JSON array that has been stringified, looping through the data, and utilizing it effectively

I'm currently exploring Node JS packages and I need some guidance. Here is an example of the JSON data that I have: [{ "name":"SpiderMan", "description":"Superhero", "head_id":"29", "domain_name":"spiderman.com" }] I am trying to figure out how to ...

Various web browsers are displaying distinct jQuery errors when executing the code

I'm currently working on validating and uploading images using multiple accept inputs with the help of jQuery, AJAX, and PHP. I have successfully added a validation function that is working correctly, but the form is not submitting. Additionally, Chro ...

Polymer 1.0: Failure to update when binding CSS classes

Looking for some help with this code snippet: <dom-module id="foo-bar"> <template> <span class$="{{getState()}}">Foo Bar</span> </template> <script> (function() { class FooBar { ...

Add a Page to Your Domain Name using the Text Input Box

I'm looking to create an input field that allows users to enter a text string, which will be added to a domain name when submitted, redirecting the user to a specific page. Here's how the process works: The user enters 'foo' into the ...

Steps to refresh a variable when the SMS read plugin successfully completes

I'm attempting to make a post call within the success callback of my SMS read plugin code. I can successfully print _this.otpnumber in the console. Please refer to my stack trace image link getSMS(){ var _this= this; var fil ...

Encountering a Basic React Issue: Unable to Implement @material-ui/picker in Next.js

I'm currently attempting to integrate the @material-ui/pickers library into my Next.js application. In order to incorporate the Picker provider, I followed the guidance provided in the Next.js documentation by adding the _app.js file inside /pages: i ...

populating a multi-dimensional array using a "for" loop in Javascript

It appears that JavaScript is attempting to optimize code, causing unexpected behavior when filling a multidimensional array (largeArr) with changing values from a one-dimensional array (smallArr) within a loop. Take the following code for example: largeA ...

Use hyphens instead of spaces in angular js data binding

<form role="form" method="POST" action="{{ url('/roles/save') }}" data-ng-app=""> <div class="form-group"> <label>Page-Title:</label> <input type="text" required value="" data-ng-model="title" name="pag ...

How can the error within a promise be captured when using resolve()?

Check out the code snippet below: userUpdate(req: Request, res: Response) { this.userTaskObj.userUpdate(req.params.id, req.body).then(() => { res.status(200).json({ status: 'OK', message: 'User updated', ...

Sorting custom strings in Javascript with special characters like dash (-) and underscore (_)

I am attempting to create a custom sorting method with the following order: special character ( - first, _ last) digit alphabets For instance, when sorting the array below var words = ['MBC-PEP-1', 'MBC-PEP01', 'MBC-PEP91&apo ...

I'm baffled by the unexpected result I'm getting when using 'foreach' in node.js

Recently delving into node.js, I've encountered a puzzling issue. I'm perplexed as to why my output appears as: ciao data data instead of: data data ciao Below is the code causing this unexpected output: fs.readdir("sender", (err, fil ...

Embedding Vue component into a traditional PHP/jQuery project

Currently, I have a large legacy web application that is primarily built using Codeigniter and jQuery. Our strategy moving forward involves gradually transitioning away from jQuery and incorporating Vuejs into the project instead. This process will involv ...

Is there a way to verify if an ID includes more than one word?

I am trying to target a specific div with a unique id in jQuery: <div id="picture_contents_12356_title"></div> The '12356' is autogenerated and must be included in the id. I need to create a jQuery selector that combines "picture_co ...

Disappearing Cloned Form Fields in jQuery

Hey there! I'm trying to duplicate a section of a form using the code below. But for some reason, the copied fields are only visible for a split-second before they disappear. Can anyone spot any errors that might be causing this strange behavior? jQu ...

What causes an "Internal Server Error" when attempting to use data for a database request with AJAX GET/POST in Laravel?

There's a unique issue that I'm struggling to resolve... Every time I drag and drop an event into the calendar, an Ajax Post Request is sent to my controller. The controller then inserts some data into the database with the event name received v ...

JavaScript - Dynamically loaded CSS: CSS variables are not immediately accessible to JavaScript, but are successfully evaluated within the CSS itself

I am encountering an issue with dynamically loading stylesheets via JavaScript into my application. Within these stylesheets, I have various CSS variables that I need to access and modify from my JavaScript code. When the stylesheets are directly embedded ...

Tips for extracting data from a JQuery table with Python

My goal is to extract information from the top ten items on a manga website using Python Selenium/BeautifulSoup. However, I am facing challenges due to the website loading its content through a jquery script. The tutorials and guides I have followed do not ...

Tips for setting a default value in a Multi Select component with reactjs and Material UI

Is it possible to set a default value on a Multiple selection (CHIP) using reactjs and material ui? Despite searching extensively online, I have not been able to find any relevant documentation addressing this issue. import * as React from 'react&apos ...

The Quasar application does not eliminate console.log() statements during production builds

I've been facing difficulties in removing the console.log() from my Quasar app for production builds. Despite checking solutions on various platforms like StackOverflow, Quasar forums, and GitHub, I am still struggling to eliminate the console.log st ...