What is the best way to implement an onclick method on a div in order to toggle the display of information

I have come across similar questions, but in my case, I am working with dynamic data from an API. I want the message body to show when a user clicks on a message with only the subject, and then be able to click again to hide the body. The current functionality works fine, but I would like to add that feature.

if(data.status == 200){

    data.data.forEach(message => {            
            msg +=  `
            <div id="read">
                <p id="header">${message.subject}<span>......</span></span></p>
                <p id="body">${message.message_details}</p>
                <p>Sent on: ${message.created_on}</p>
            </div>
            <hr>`
        
    });
    document.getElementById("inbox").innerHTML = msg
    
}

Answer №1

To start, make sure to place all of your dynamic blocks within a wrapper div, which we can name articles, for instance.

Next, add an eventListener to this wrapper to listen for the click event and then verify if the clicked element is the title. If so, toggle the hide class that is predefined in the css. See the example below:

const wrapperEl = document.querySelector('#articles');

wrapperEl.addEventListener('click', function(e){
    if(e.target.id == 'header'){
      e.target.nextElementSibling.classList.toggle('hide')
    }

});
.hide {
 display: none
}
<div id="articles">
  <div>
    <p id="header">title 1<span>......</span></p>
    <p id="body" class="hide">article content here</p>
    <p>Sent on: 02/17/2020</p>
  </div>
  <hr />
  <div>
    <p id="header">title 2<span>......</span></p>
    <p id="body" class="hide">article content here</p>
    <p>Sent on: 02/17/2020</p>
  </div>
  <hr />
  <div>
    <p id="header">title 3<span>......</span></p>
    <p id="body" class="hide">article content here</p>
    <p>Sent on: 02/17/2020</p>
  </div>
  <hr />
  <div>
    <p id="header">title 4<span>......</span></p>
    <p id="body" class="hide">article content here</p>
    <p>Sent on: 02/17/2020</p>
  </div>
</div>

NOTE: In this specific example, I have included hardcoded blocks for testing purposes. However, in your scenario, these would be fetched from an API dynamically. Regardless, they should always be enclosed within a wrapper element.

Answer №2

Implemented the necessary code to conceal body div, and utilized class="body" instead of id for paragraph and div elements, as they will be duplicated.

const data = [
{subject: "test123", message_details: "msg123", created_on: "12-05-2021"},
{subject: "test456", message_details: "msg456", created_on: "02-05-2020"},
{subject: "test789", message_details: "msg789", created_on: "11-07-2011"},
];

let msg = "";
data.forEach(message => {            
                msg +=  `
                <div class="read">
                    <p id="header">${message.subject}<span>......</span></span></p>
                    <p class="body">${message.message_details}</p>
                    <p>Sent on: ${message.created_on}</p>
                </div>
                <hr>`
                
});
document.getElementById("inbox").innerHTML = msg;

const bodyElements = document.querySelectorAll(".read");
bodyElements.forEach(function(bodyEle) {
  bodyEle.addEventListener("click", (e) => {
    bodyEle.children[1].classList.toggle("hide");
  });
});
.hide {
 display: none;
}
<html>
<head></head>
<body>
<h1>My title</h1>
<div id="inbox">
</div>
</body>
</html>

Answer №3

Avoid using repeated IDs in your code; instead, utilize classes to ensure uniqueness.

Whether you are utilizing axios or the fetch API, the approach remains the same:

axios.get('api-url').then(response => {
  // Generate HTML content here
}).then(() => {
   document.querySelectorAll('.header').forEach(x => x.addEventListener('click', toggleBody));
})

const toggleBody = (event) => {
  event.closest('.read').querySelector('.body').classList.toggle('is-open')
}

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

Creating an Observable Collection in Angular using AngularFire2 Firestore

I am currently using material 2 and attempting to develop data tables with pagination and sorting. In order to achieve this, I require my collections to be observable. However, I believe that I might be incorrectly populating or initializing the arrays in ...

Is there a way to automatically activate the "Add" button when I hit the enter key in the text box?

Being someone who relies on to-do lists, I implemented a system where you can input tasks into a textbox and click the add button to see them listed below. However, I found it cumbersome to keep clicking the add button every time I wanted to quickly add mu ...

Using AngularJS, you can pass serialized objects as query string parameters

I'm trying to pass nested objects as query parameters from my AngularJS Controller using the following code: $scope.redirect = function () { const params = $httpParamSerializer({ initval: { user: { id: 1, ...

Ajax requests are returning successful responses for GET and POST methods, however, no response is being received for

When I make a POST request within the same domain ( -> ), the responseXML contains the expected data. However, when I make the same request as a PUT, the responseXML is null for a successful request. I have tried using jQuery.ajax and even implemented i ...

What is the best way to modify a current state object without causing an endless loop of redirects?

const useCase = (argument) => { const [value, setValue] React.useState(argument) React.useEffect(() => setValue({...value ...argument), [argument, value, setValue]) } The above code is currently causing an infinite loop due to setting the stat ...

How can I store all selected dropdown values in the URL parameters whenever a dropdown option is changed?

In mypage.php, I have set up three drop-down menus: <select name='vehicle'> <option value=''>Select</option> <option value='bus'>Bus</option> <option value='bike'>Bike</o ...

React/Next Component Changes State and Clears it in useEffect

Currently, I am faced with an issue while attempting to fetch data from an API. The problem arises during the rendering process since the useEffect function is being called multiple times. Surprisingly, everything works perfectly fine during the initial pa ...

Using React to easily rearrange images by dragging and dropping them

Currently, I am working on incorporating drag-and-drop functionality using React JS along with the react-dropzone library to display thumbnails. The code implementation is provided below: import React from "react"; import ReactDOM from "react-dom"; impor ...

v-bind is not recognizing modifications in the array elements (vue js)

I'm currently working on switching the id of an image upon the user clicking a button. At first, the id should be set to B0_h, but once the user clicks the button, it should trigger a change in an array value to true. Initially, all values in the arra ...

The selection elements fail to reset correctly

I'm currently working on an Angular 4 application where I have a form that includes a select element inside a box. <div class="form-group"> <label for="designation">Designation</label> <select [class.red-borde ...

Exploring the Method of Accessing data-* Attributes in Vue.js

I have a button that, when clicked, triggers a modal to open. The content displayed in the modal is determined by the data attributes passed to the button. Here is my button: <button class="btn btn-info" data-toggle="modal" data-t ...

Executing an AJAX request to insert data into MySQL

After my extensive online search, I came across a solution that involves using ajax to set information in my database. While browsing through this page, I learned how to retrieve data from the database. My specific query is: can we also use ajax to set in ...

Exploring issues with jQuery

I'm encountering an issue with my code. I have multiple divs with the same classes, and when I click on (toggle#1) with the .comments-toggle class, all divs below toggle-container expand. What I actually want is for only the div directly below .commen ...

Applying a dynamic translate3d transformation on the ::after element using CSS3

My current challenge involves manipulating a pseudo ::after element using translate3d If I hardcode the values, it's straightforward: div::after { ... transform: translate3d(40px, 40px, 0); } Now, I want to dynamically set the value for the ...

What could be causing my Three.js code to fail during testing?

Recently, I decided to delve into the world of Three.js by following a thorough tutorial. While everything seemed perfectly fine in my code editor of choice (Visual Studio Code 2019), I encountered a frustrating issue when I attempted to run the code and n ...

Adjust the size of the FabricJS canvas within a child component in VueJS

In my project, I am using VueJS and FabricJS to create a dynamic canvas that changes size based on user input. The goal is to have the canvas adjust its dimensions as soon as the user enters new values in the sidebar component. Despite using $emit from ch ...

Conceal the div element if the screen size drops below a certain threshold

Is it possible to hide a div element when the browser width is less than or equal to 1026px using CSS, like this: @media only screen and (min-width: 1140px) {}? If not, what are some alternative solutions? Additional information: When hiding the div eleme ...

Exploring Angular 6's nested routes and corresponding components for child navigation

I'm currently diving into the concept of lazy loading in Angular 6. Here's a visual representation of the structure of my application: ─src ├───app │ ├───components │ │ ├───about │ │ ├─── ...

Sort through an array using criteria from another array

const items = [[{name:"p2"},{name:"p3"}, {name:"p7"},{name:"p9"},{name:"p1"}],[{name:"p6"}, {name:"p3"},{name:"p7"}, {name:"p9"},{name:"p2"}],[{name:"p ...

The expected React component's generic type was 0 arguments, however, it received 1 argument

type TCommonField = { label?: string, dataKey?: string, required?: boolean, loading?: boolean, placeholder?: string, getListOptionsPromissoryCallback?: unknown, listingPromissoryOptions?: unknown, renderOption?: unknown, getOptionLabelFor ...