A strategy for concealing the selected button within a class of buttons with Vanilla JS HTML and CSS

I have encountered a challenging situation where I am using JavaScript to render data from a data.json file into HTML. Everything seems to be functioning correctly, as the JSON data is being successfully rendered into HTML using a loop, resulting in multiple objects with the same class.

However, due to this setup, every button I create ends up belonging to the same class within the loop. Now, here's my dilemma: I want to hide only the specific button that is clicked, not all buttons of the same class.

var X = document.getElementsByClassName("buttons");
function HideClickedButton() {

  for (let x of X) {
    if (x.style.display === "none") {
      x.style.display = "block";
    
    } else {
      x.style.display = "none";
    }
  }
}

for (const button of X) {
    button.addEventListener('click', HideClickedButton);
}
<button class="buttons">Test</button>
<button class="buttons">Test</button>
<button class="buttons">Test</button>
<button class="buttons">Test</button>

The code above currently hides all buttons with the same class when one is clicked.

If I use just

document.querySelector(".buttons").style.display = "none"
,

it always hides the first button regardless of which button is pressed.

Edited Section:

 <div onclick="addToCart(${product.price})">
    <button class="b1" onclick="hideAddButton(this)" type="button">ADD</button>
  </div>
  <div onclick="addToCartRemove(${product.price})">
    <button class="b2 hidden" onclick="showRemoveButton(this)" type="button">Remove</button>
  </div>

My JavaScript code looks something like this, where I am rendering a list from JSON. After rendering, there are a total of 12 buttons. They are grouped in sets of 6 (see image). Now, I do not want to initially display the remove button. It should only appear when the corresponding ADD button is clicked. Upon clicking the ADD button, it will disappear and the Remove button will take its place, while the other ADD buttons remain visible. Please let me know if you understand.https://i.stack.imgur.com/8A5Ht.png

Answer №1

To handle button clicks, you can either add an event listener to each button individually and hide the clicked element dynamically...

const buttons = document.querySelectorAll('.button');

buttons.forEach(button => {
  addEventListener('click', handleClick)
});

function handleClick(e) {
  e.target.classList.add('hide');
}
.hide { display: none; }
<button class="button">one</button>
<button class="button">two</button>
<button class="button">three</button>
<button class="button">four</button>
<button class="button">five</button>

...or you can wrap all your buttons in a container, employ event delegation, and attach only one listener to that container (which captures events from all child elements as they bubble up the DOM). Ensure the clicked element has the class "button", then hide it.

const buttons = document.querySelector('.buttons');

buttons.addEventListener('click', handleClick);

function handleClick(e) {
  if (e.target.matches('.button')) {
    e.target.classList.add('hide');
  }
}
.hide { display: none; }
<div class="buttons">
  <button class="button">one</button>
  <button class="button">two</button>
  <button class="button">three</button>
  <button class="button">four</button>
  <button class="button">five</button>
</div>

Answer №2

To achieve this functionality, you can utilize the onclick event with "yourfunction(this)", as demonstrated in the snippet below.

Alternatively, you can implement an event listener for a different approach.

function HideClickedButton(x) {
      x.style.display = "none";
}
<div>
  <button onclick="HideClickedButton(this)" class="buttons">Button 1</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 2</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 3</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 4</button>
</div>

EDIT: In response to your question in the comments, here is how you can toggle the display of button 1 when clicking button 8, and vice versa. The buttons' classes are not relevant in this case as the function is triggered by the onclick attribute, not their class definitions.

function HideClickedButton(x) {
      var parent = x.parentNode;
      var index = [].indexOf.call(parent.children, x);
      // if the clicked element is at index 0 in the parent's children (button 1)
      if(index==0){
        // show the element at index 7 (button 8)
        parent.children[7].style.display = "inline-block"; 
      }
      // otherwise, if the clicked element is at index 7 in the parent's children (button 8)
      else if(index==7){
        // hide or show the element at index 0 (button 1)
        parent.children[0].style.display = "inline-block"; 
      }
      // then hide the clicked button
        x.style.display = "none";
}
<div>
  <button onclick="HideClickedButton(this)" class="buttons">Button 1</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 2</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 3</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 4</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 5</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 6</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 7</button>
  <button onclick="HideClickedButton(this)" class="buttons_other_class">Button 8</button>
</div>

Answer №3

To create interaction with your button, you can set up an event listener for the click action.

var btns = document.querySelectorAll(".buttons");
    btns.forEach(function (btn) {
        btn.addEventListener("click", function () {
            this.style.display = "none";
        })
    })

Answer №4

  1. document.querySelector() will only select the first element that matches the selector. To get all elements that match, use document.querySelectorAll().
  2. An easier way to handle this is to attach event handlers to all your buttons once they are rendered.

You seem to imply that when a button is clicked, it should disappear while the other buttons reappear. If this is not the desired behavior, you can comment out the line of code that changes the style of "other" buttons to block.

Edit: e.PreventDefault() and e.StopPropagation() are included to prevent the standard button click behavior (such as submitting forms). If you do not want to suppress this behavior, you can simply remove these lines.

const buttons = document.getElementsByClassName('buttons');

[...buttons].forEach( (button) => {
   button.addEventListener( 
      'click', 
      (e) => HideClickedButton( e, button ), 
      false 
   );
});

function HideClickedButton( e, button ) {
  [...buttons].forEach( (other) => other.style.display = 'block' );
  e.preventDefault();
  e.stopPropagation();
  button.style.display = 'none';
}
<div>
  <button class="buttons">Button 1</button>
  <button class="buttons">Button 2</button>
  <button class="buttons">Button 3</button>
  <button class="buttons">Button 4</button>
</div>

Answer №5

var X = document.getElementsByClassName("buttons");
function ToggleButtonVisibility() {

  for (let x of X) {
    if (x.style.display === "none") {
      x.style.display = "block";
    
    } else {
      x.style.display = "none";
    }
  }
}

for (const button of X) {
    button.addEventListener('click', ToggleButtonVisibility);
}
<button class="buttons">Test</button>
<button class="buttons">Test</button>
<button class="buttons">Test</button>
<button class="buttons">Test</button>

HTML:

<button class="hidden-button">Click me</button>

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

How can you stop a document event listener from triggering?

Utilizing document.addEventListener('touchstart', this.onDocument); allows me to recognize when a user taps outside of an element. However, within my button click handler, the following code is present: toggleItemActive(e) { e.stopPropa ...

Have Vue props been set to null?

Currently, I have a component within my vue.js application that looks like this: export default { props: ['forums'], methods: { increment(forum, index) { ForumService.increment(forum) .then(() => { ...

Comparing Embedded and Linked JS/CSS

In my experience, I understand the advantages of using linked CSS over embedded and inline styles for better maintainability and modularity. However, I have come across information suggesting that in certain mobile web development applications, it may be m ...

Issue with Material-UI Dialog Reusable Component: No error messages in console and app remains stable

Here is a component I've created for reusability: import { Dialog, DialogContent, DialogContentText, DialogTitle, Divider, Button, DialogActions, } from "@mui/material"; const Modal = ({ title, subtitle, children, isOpen, hand ...

Designing a carousel-style menu list with navigation buttons for moving forward and backward

I'm running into some trouble while attempting to create a carousel. Firstly, the issue I am facing is that when you continuously click on the Next button, the function keeps working even after reaching the last item. I'm not sure how to make th ...

Guide on parsing logs containing JSON objects utilizing Fluentd

In my nginx log file, I come across lines like this: 127.0.0.1 192.168.0.1 - [28/Feb/2013:12:00:00 +0900] "GET / HTTP/1.1" 200 777 "-" "Opera/12.0" - <{"key1":"value1","key2":98765,"key3":false,"key4":["one","two"],"key5":{"key22":98765,"key23":false,"k ...

What is the best way to receive the result of an asynchronous function as an input and showcase it using express?

I have recently started learning about node and express My goal is to create an API that can fetch data from an external source and use that data for my application Is there a way to retrieve the result of an asynchronous method and display it using the ...

Immediate self-invocation occurs within a JavaScript function

My goal is to dynamically create a DOM button object with JavaScript, and it seems to be happening perfectly fine. However, I'm facing an issue where if I try to assign another JavaScript function to one of the buttons, the other script triggers itsel ...

Chrome is having trouble setting the cookie with the Set-Cookie header

I am making an AJAX call to another service's API, expecting to receive a cookie that will be stored in my browser for future API calls. Unfortunately, even though the response headers contain a 'Set-Cookie' header, the cookie is not being s ...

Hold off on progressing until the http.get request in Angular 4 has completed

Currently, I am in the process of creating a new registration form for an app using Ionic and utilizing ASP.Net(C#) for my API. My objective is to validate if a user already exists when the input blur event is triggered. However, I'm encountering an ...

Tips for transferring information to an input field's value

There's an input box with an empty value that needs to be filled with data. <input type="text" value="" class="box"> $('.skills-tags').on('click', function(){ var value = $(".skills-tags").val(); $('.label-pr ...

Failed commitments in Protractor/WebDriverJS

WebdriverIO and Protractor are built on the concept of promises: Both WebdriverIO (and as a result, Protractor) APIs operate asynchronously. All functions return promises. WebdriverIO maintains a queue of pending promises known as the control flow to ...

What is the best way to format a User object into JSON before sending it to an API endpoint?

Encountering an error 400 when attempting to submit a POST request. "$.User": [ "The JSON value could not be converted to WebApi.Models.User. Path: $.User | LineNumber: 5 | BytePositionInLine: 19." ] } Detailing my Order Model with ...

Leveraging the power of AWS API Gateway and Lambda for seamless image upload and download operations with Amazon

I have successfully created a lambda function to handle image uploads and downloads to s3. However, I am encountering difficulties with the proxy integration from the API Gateway. Despite reviewing the documentation and looking at this specific question ...

Fullcalendar JS will easily identify dates with events, allowing users to simply click on those dates to redirect to a specific URL

When looking at the official example, we can see that the events are displayed in a typical calendar format: https://fullcalendar.io/js/fullcalendar-3.5.0/demos/basic-views.html Each event is listed in the calendar, and clicking on an individual event wi ...

Error code 1 occurs when attempting to execute the "npm run start" command

Every time I attempt to execute "npm run start" within my project folder, the following error message pops up: myLaptop:app-name userName$ npm run start > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c1a0b1b1ecafa0aca481f ...

Inserting POST request data into subdocument arrays of a database

I am struggling to add data to a nested mongoose sub-document when creating a new schema from the client side. Only the data that is not nested inside another schema/array is being sent over to the database. My database setup includes MongoDB with Mongoos ...

Vertx throwing a class cast exception

Performing a POST request as defined in Swagger: post: tags: - entries summary: Add an entry to the phonebook operationId: addEntry produces: - application/json consumes: - application/json p ...

Extract the innerHTML input value of each row in an HTML table

I've encountered an issue with my HTML table that contains static values, except for one cell which has an input field. When I try to convert the row data into JSON, the single input field is causing complications. Without the input field, I can suc ...

Navigating between components using AngularJS and ExpressJS

Currently, I am embarking on a project that involves utilizing express and angularjs. To guide me through this process, I have been referring to this particular tutorial. Upon my initial attempt of running localhost:3000, I successfully loaded my index.jad ...