Emac
Emac

Reputation: 1167

Javascript / JQuery getting value out of input boxes on table

I have a table with input from Flask, and some fields of the table have input boxes for the user. I am trying to get the value of what they input and I am struggling. I figure this is an easy question for people here, but I have been banging my head against my desk for a while now and searched the forums here without figuring out what I'm doing wrong.

I created a similar but much simpler HTML table to what I have for us to play around with. I have not been able to get to the radio button part yet because I'm still trying to get the input box part solved, but I will be needing to get both of those. Ideally, I'd be returning each row into a JSON array.

The JQuery I included returns "Cannot read property 'GetElementsByTagName' of undefined", but it's only one of the many examples I've tried without any success. I've tested variations with .value, .text, .innerHTML, but I just can't get what's inside the box (or the radio button value for that matter).

Any help for a JS novice?

//$('.tableRow').each(function() {
//  favoriteBeer = document.getElementsByClassName('favoriteBeer').document.GetElementsByTagName('input');
//  console.log(favoriteBeer);
//});
table {
  border-collapse: collapse;
}

table,
th,
td {
  border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable">
  <thead>
    <tr>
      <th>Name</th>
      <th>Age</th>
      <th>Favorite Food</th>
      <th>Favorite Beer</th>
    </tr>
  </thead>
  <tbody>
    <tr class='tableRow'>
      <td>John</td>
      <td>30</td>
      <td><label><input type="radio" name="favoriteFood1" value="Pizza"/>Pizza</label><label><input type="radio" name="favoriteFood1" value="Tacos" />Tacos</label>
        <td><input type="text" class="favoriteBeer"></td>
    </tr>
    <tr class='tableRow'>
      <td>Joe</td>
      <td>25</td>
      <td><label><input type="radio" name="favoriteFood2" value="Pizza"/>Pizza</label><label><input type="radio" name="favoriteFood2" value="Tacos"/>Tacos</label>
        <td><input type="text" class="favoriteBeer"></td>
    </tr>
    <tr class='tableRow'>
      <td>Sam</td>
      <td>50</td>
      <td><label><input type="radio" name="favoriteFood3" value="Pizza"/>Pizza</label><label><input type="radio" name="favoriteFood3" value="Tacos"/>Tacos</label>
        <td><input type="text" class="favoriteBeer"></td>
    </tr>
  </tbody>
</table>

Upvotes: 3

Views: 74

Answers (3)

Scott Marcus
Scott Marcus

Reputation: 65806

You can't call document.getElementsByTagName() on the results of .getElementsByClassName() because .getElementsByClassName() returns a "node list" and a node list doesn't have a document property. But you could do this:

favoriteBeer = document.getElementsByClassName('favoriteBeer').getElementsByTagName('input');

Because most DOM query methods can be called on document, a node, or a node list.

However, .getElementsByClassName() and .getElementsByTagName() both return "live" node lists, which means that every time you reference the variable that you've assigned the results to, the entire document must be re-scanned to ensure you get the most up-to-date results. This is only valuable when you have elements being created/destroyed dynamically. If you aren't working with that kind of code, the use of these methods is discouraged because they are very wasteful, in terms of performance.


Now, since you are using JQuery, you should use it consistently. Just pass a valid CSS selector into the JQuery object to scan the DOM for matching elements.

So, you can simply pass the class name into JQuery to obtain a set of references to your DOM objects and then get the value property of those input elements. But, you do have to wait to run that code until after the user has had a chance to enter some data. I've added a button element to your code which you can click when you are ready to see the input values.

$("button").on("click", function(){
  // Just passing a valid CSS selector to the JQuery object will
  // return a JQuery "wrapped set" of all matching elements.
  
  // Then, the .each() method takes a function that will automatically
  // be passed the index of the current element being iterated, a DOM reference
  // to the element itself, and a reference to the wrapped set (not used here).
  $('.favoriteBeer').each(function(index, element) {
   // You can use the element argument inside of the .each() loop
   // or you can use the "this" keyword to get the same DOM reference
   console.log(element.value, this.value);
  });
});
table {
  border-collapse: collapse;
}

table,
th,
td {
  border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable">
  <thead>
    <tr>
      <th>Name</th>
      <th>Age</th>
      <th>Favorite Food</th>
      <th>Favorite Beer</th>
    </tr>
  </thead>
  <tbody>
    <tr class='tableRow'>
      <td>John</td>
      <td>30</td>
      <td><label><input type="radio" name="favoriteFood1"/>Pizza</label><label><input type="radio" name="favoriteFood1" />Tacos</label>
        <td><input type="text" class="favoriteBeer"></td>
    </tr>
    <tr class='tableRow'>
      <td>Joe</td>
      <td>25</td>
      <td><label><input type="radio" name="favoriteFood2"/>Pizza</label><label><input type="radio" name="favoriteFood2" />Tacos</label>
        <td><input type="text" class="favoriteBeer"></td>
    </tr>
    <tr class='tableRow'>
      <td>Sam</td>
      <td>50</td>
      <td><label><input type="radio" name="favoriteFood3"/>Pizza</label><label><input type="radio" name="favoriteFood3" />Tacos</label>
        <td><input type="text" class="favoriteBeer"></td>
    </tr>
  </tbody>
</table>
<button type="button">Get Data</button>

Upvotes: 3

Zakaria Acharki
Zakaria Acharki

Reputation: 67505

Use a for loop with the help of $(this) to get the related values of every row, and get the selected radio buttons using input:radio:checked as selector like :

$('button').click(function() {
  $('.tableRow').each(function() {
    var favoriteBeer = $(this).find('.favoriteBeer').val();
    var favoriteFood = $(this).find('input:radio:checked').val();

    var dataObj = {
      favoriteBeer: favoriteBeer,
      favoriteFood: favoriteFood
    };

    console.log(dataObj);
  });
})
table {
  border-collapse: collapse;
}

table,
th,
td {
  border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable">
  <thead>
    <tr>
      <th>Name</th>
      <th>Age</th>
      <th>Favorite Food</th>
      <th>Favorite Beer</th>
    </tr>
  </thead>
  <tbody>
    <tr class='tableRow'>
      <td>John</td>
      <td>30</td>
      <td><label><input type="radio" name="favoriteFood1" value="Pizza"/>Pizza</label><label><input type="radio" name="favoriteFood1" value="Tacos" />Tacos</label>
        <td><input type="text" class="favoriteBeer"></td>
    </tr>
    <tr class='tableRow'>
      <td>Joe</td>
      <td>25</td>
      <td><label><input type="radio" name="favoriteFood2" value="Pizza"/>Pizza</label><label><input type="radio" name="favoriteFood2" value="Tacos"/>Tacos</label>
        <td><input type="text" class="favoriteBeer"></td>
    </tr>
    <tr class='tableRow'>
      <td>Sam</td>
      <td>50</td>
      <td><label><input type="radio" name="favoriteFood3" value="Pizza"/>Pizza</label><label><input type="radio" name="favoriteFood3" value="Tacos"/>Tacos</label>
        <td><input type="text" class="favoriteBeer"></td>
    </tr>
  </tbody>
</table>
<button type="button">Retrieve Data</button>

Upvotes: 3

AmmoPT
AmmoPT

Reputation: 958

You cannot run this line:

favoriteBeer = document.getElementsByClassName('favoriteBeer').document.GetElementsByTagName('input');

Because document of element .favoriteBeer is undefined.

Also, when $('.tableRow').each(function() runs, the input field is empty, as it runs as the page loaded. So what you can do instead is listen on the keyup event and check the current value of input every time the user types something.

Like so:

$('.favoriteBeer').keyup(function() {
  console.log($(this).val());
});
table {
  border-collapse: collapse;
}

table,
th,
td {
  border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable">
  <thead>
    <tr>
      <th>Name</th>
      <th>Age</th>
      <th>Favorite Food</th>
      <th>Favorite Beer</th>
    </tr>
  </thead>
  <tbody>
    <tr class='tableRow'>
      <td>John</td>
      <td>30</td>
      <td><label><input type="radio" name="favoriteFood1"/>Pizza</label><label><input type="radio" name="favoriteFood1" />Tacos</label>
        <td><input type="text" class="favoriteBeer"></td>
    </tr>
    <tr class='tableRow'>
      <td>Joe</td>
      <td>25</td>
      <td><label><input type="radio" name="favoriteFood2"/>Pizza</label><label><input type="radio" name="favoriteFood2" />Tacos</label>
        <td><input type="text" class="favoriteBeer"></td>
    </tr>
    <tr class='tableRow'>
      <td>Sam</td>
      <td>50</td>
      <td><label><input type="radio" name="favoriteFood3"/>Pizza</label><label><input type="radio" name="favoriteFood3" />Tacos</label>
        <td><input type="text" class="favoriteBeer"></td>
    </tr>
  </tbody>
</table>

Upvotes: 1

Related Questions