Home > Mobile >  Changing innerHTML based on specific button click using assigned values returns undefined
Changing innerHTML based on specific button click using assigned values returns undefined

Time:04-06

I have a form that I'm using for orders. I'm using the same form for every order but I want to replace the last word in the text string of the header (in this case "Food") to show what the customer is ordering based on the button they clicked. For this example, I've just made a simple layout with three buttons that are each assigned a value inside their button tags. The same button style is going to be used all throughout, it's just going to have a different name and value assigned to it for the form. I've also made a close button to simulate the user closing the form and forcing the last word in the header back to its default Food just in case they manage to open the form without actually clicking a button so they don't see something like "Order Your null". So ideally, the user would click their choice of food and the header title would change to "Order Your [Food Value]"

The problem I'm having is that I can't figure out how to collect the values and change the innerHTML based on what was clicked using javascript. If it were only three buttons I could write three separate expressions but on my project, I've got about 40 items and buttons total so I'd rather label 40 buttons with values and use one script to power them all as opposed to writing an expression for every button (completely possible but not very efficient for myself or the user's browser I would imagine...).

The script runs but returns an "undefined" value. I've tried changing the let food = document. attribute to just about anything I could find on Google and nothing is returning a value (or an error for that matter).

https://jsfiddle.net/astombaugh/kf2vgq0p/550/

<body>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

  <div >Order Your<div id="foodHeader">Food</div>
  </div>
  <div >
    <a  name="foodItem" value="Cheeseburger">Order Your Cheeseburger</a>
    <a  name="foodItem" value="Salad" style="background-color: green">Order Your Salad</a>
    <a  name="foodItem" value="Sub" style="background-color: blue">Order Your Sub</a>
  </div>
  <div >
    <a >
      X
    </a>
  </div>
</body>
.foodHeader {
  display: block;
  font-family: Helvetica Neue, Helvetica, Arial;
  font-weight: 700;
  text-align: center;
  color: black;
  font-size: 3rem;
  margin: 0 auto;
}

.btnContainer {
  display: flex;
  flex-direction: row;
}

.orderBtn {
  display: block;
  font-family: Helvetica Neue, Helvetica, Arial;
  font-weight: 700;
  text-align: center;
  color: white;
  width: 200px;
  height: 50px;
  margin: 0 auto;
  background-color: red;
  font-size: 1rem;
  padding: 10px 10px;
  line-height: 3rem;
  outline: 1px solid black;
}

.closeBtnContainer {
  display: block;
  margin: 20px auto;
  text-align: center;
}

.closeBtn{
  background-color: black;
  color: white;
  width: 20px;
  height: 20px;
  margin: 0px auto;
  padding: 10px;
  text-align: center;
  cursor: pointer;
}
        let food = document.querySelectorAll('foodItem').value;
        let foodHeaderText = document.getElementById('foodHeader');
        const orderBtn = document.getElementsByClassName('orderBtn');
    const closeBtn = document.getElementsByClassName('closeBtn');


        for (let order = 0; order < orderBtn.length; order  ) {
          orderBtn[order].addEventListener('click', function() {
            foodHeaderText.innerHTML = food;
          })
        }
    
    for (let close = 0; close < closeBtn.length; close  ) {
          closeBtn[close].addEventListener('click', function() {
            foodHeaderText.innerHTML = "Food";
          })
        }

CodePudding user response:

Reason why you are getting undefined is because

let food = document.querySelectorAll('foodItem').value;

definitely is undefined: querySelectorAll return a collection, and has no property value. Besides, you want to dynamically get the value at each click, not once for all.

Replace code buy:

function(e) {
  foodHeaderText.innerHTML = e.target.getAttribute("value") || "food";

CodePudding user response:

The function you pass to the event listeners accepts a parameter, that is the event object. You can find more here. Given that, you can arrange a solution like the following:

let foodHeaderText = document.getElementById('foodHeader');
const orderBtn = document.getElementsByClassName('orderBtn');
const closeBtn = document.getElementsByClassName('closeBtn');


for (let order = 0; order < orderBtn.length; order  ) {
  orderBtn[order].addEventListener('click', function(event) {
    foodHeaderText.innerHTML = event.target.attributes["value"]["value"];
  })
}
    
for (let close = 0; close < closeBtn.length; close  ) {
  closeBtn[close].addEventListener('click', function(event) {
    foodHeaderText.innerHTML = "Food";
  })
}

CodePudding user response:

I believe your issue is in this line:

let food = document.querySelectorAll('foodItem').value;

You could try this:

let food = Array.from(document.querySelectorAll('[name="foodItem"]')).map(el => el.getAttribute('value'))

Hope this helps.

CodePudding user response:

food isn't defined as a string. In fact, it's undefined because you're trying to retrieve all foodItem elements at once before they're even clicked. As others have said - that's a NodeList and won't have a value property.

You code can be updated to:

for (let order = 0; order < orderBtn.length; order  ) {
  orderBtn[order].addEventListener('click', function(e) {
    foodHeaderText.innerHTML = e.target.value;
  });
}

Or, to be a little more modern:

document.getElementsByClassName("orderBtn").forEach(orderBtn => {
  orderBtn.addEventListener("click", e => {
    foodHeaderText.textContent = e.target.value;
  });
});

Or, even better, don't use tons of listeners - just add one to the parent container:

document.querySelector(".btnContainer").addEventListener("click", e => {
  if (e.target.matches(".orderBtn")) {
    foodHeaderText.textContent = e.target.value;
  }
}
  • Related