Home > Blockchain >  Can't apply other const within a forEach function
Can't apply other const within a forEach function

Time:05-30

I am new to Javascript.

So far my code only changes the color of the text of the button, I am trying to make it where enabling the button also reveals the hidden paragraph. Always says that the arrow and answers are undefined

const buttons = document.querySelectorAll('button');
const answers = document.querySelectorAll('p');
const arrows = document.querySelectorAll('arrow');
console.log(buttons);
console.log(answers);
console.log(arrows);


buttons.forEach(button => {
    button.addEventListener('click', function(){
        button.style.color = 'red';
        answers.style.display = 'block';
    });
})

Alternate code i did was

const button = document.querySelector('button');
const answers = document.querySelector('.answer');
const arrow = document.querySelector('.arrow');


button.addEventListener('click', () => {
    answers.style.display = 'block';
    arrow.style.transform = 'rotate(180deg)'

});

This one worked. However, I would have to label every element in my HTML that needs to change.

Here is sample HTML:

<div >
          <button>How many team members can I invite? <img  src="images/icon-arrow-down.svg"></button>
          <p >You can invite up to 2 additional users on the Free plan. There is no limit on
          team members for the Premium plan.</p>
        </div>
        <div >
          <button>What is the maximum file upload size?<img src="images/icon-arrow-down.svg"> </button>
          <p > No more than 2GB. All files in your account must fit your allotted storage space.</p>
        </div>
        <div >
          <button>How do I reset my password?<img  src="images/icon-arrow-down.svg"></button>
          <p >Click “Forgot password” from the login page or “Change password” from your profile page.
            A reset link will be emailed to you.
          </p>
        </div>
        <div >
            <button>Can I cancel my subscription?<img  src="images/icon-arrow-down.svg"></button>
          <p >Yes! Send us a message and we’ll process your request no questions asked.</p>
        </div>
        <div >
           <button>Do you provide additional support?<img  src="images/icon-arrow-down.svg"></button>
          <p >Chat and email support is available 24/7. Phone lines are open during normal business hours.</p>

CodePudding user response:

You should grab the clicked element from inside the click event handler using window.event.target. Your problem was trying to access from your click handler to variables defined outside of its scope and having a different meaning. Everytime the click handler gets invoked it needs a strategy to fetch the clicked element and all the elements bound to its context to which you wish to change the style.

But there's a chance I didn't correctly get what you were really asking... in that case I hope to hear a feedback.

I made a demo here to show how:

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

function resetButtonStyles(){
  document.querySelectorAll('div.parent.active').forEach( divactive =>{
    divactive.classList.remove('active');
  });
}

buttons.forEach(button => {
    button.addEventListener('click', function(){
    
      document.querySelector('div.parent.active')
        ?.classList.remove('active');

      const clickedButton = window.event.currentTarget;
      const parentDiv = clickedButton.closest('div.parent');
      const boundAnswer = parentDiv.querySelector('p');

      parentDiv.classList.add("active");

      //clickedButton.style.color = 'red';
      //boundAnswer.style.border = 'solid red 2px';
    });
})
.active p{
  color: red;
}

.active button{
  border: solid red 2px;
}
<div >
  <p>Answers 1</p>
  <button>Button 1</button>
</div>

<div >
  <p>Answers 2</p>
  <button>Button 2</button>
</div>

<div >
  <p>Answers 2</p>
  <button>Button 2</button>
</div>

<div >
  <p>Answers 2</p>
  <button>Button 2</button>
</div>

CodePudding user response:

It sound like you're after an accordion effect.

  1. Wrap your markup in a container so you can use event delegation.

  2. Cache the container, and the answer elements.

  3. When you click on a button hide all the answers, switch the arrow, and then show that button's answer.

[Note: I've used unicode in CSS to show the arrows instead of images].

// Cache the elements
const container = document.querySelector('.container');
const answers = document.querySelectorAll('.answer');
const arrows = document.querySelectorAll('.arrow');

// Add a listener to the container
container.addEventListener('click', handleClick, false);

function handleClick(e) {

  // If we click a button
  if (e.target.matches('button')) {

    // Remove all the answers
    answers.forEach(answer => answer.classList.remove('show'));

    // Update the arrows
    arrows.forEach(arrow => {
      arrow.classList.remove('down');
      arrow.classList.add('right');
    });
    
    // Get the parent of the clicked element
    const parent = e.target.closest('.faq');

    // Change the arrow...
    const arrow = e.target.querySelector('.arrow');
    arrow.classList.remove('right');
    arrow.classList.add('down');
    
    // ...and then show the answer
    const answer = parent.querySelector('.answer');
    answer.classList.add('show');

  }

}
.answer { display: none; }
.show { display: block; }
.down:after { content: '\1F783'; }
.right:after { content: '\1F782'; }
button:hover { cursor: pointer; }
<div >
  <div >
    <button>How many team members can I invite?
      <span ></span>
    </button>
    <p >You can invite up to 2 additional users on the Free plan. There is no limit on team members for the Premium plan.</p>
  </div>
  <div >
    <button>What is the maximum file upload size?
      <span ></span>
    </button>
    <p > No more than 2GB. All files in your account must fit your allotted storage space.</p>
  </div>
  <div >
    <button>How do I reset my password?
      <span ></span>
    </button>
    <p >Click “Forgot password” from the login page or “Change password” from your profile page. A reset link will be emailed to you.
    </p>
  </div>
  <div >
    <button>Can I cancel my subscription?
      <span ></span>
    </button>
    <p >Yes! Send us a message and we’ll process your request no questions asked.</p>
  </div>
</div>

CodePudding user response:

const buttons = document.getElementsByTagName('button');
const answers = document.getElementsByTagName('p');
const arrows = document.getElementsByTagName('arrow');
console.log(buttons);
console.log(answers);
console.log(arrows);


for (var j = 0; j < buttons.length; j  ){
       var button = buttons[j];
       button.addEventListener('click', function(){
           button.style.color = 'red';
           for (var i = 0; i < answers.length; i  ){
             answers[i].style.display = 'block'
           }        
    });
}
  • Related