admin管理员组

文章数量:1431398

There is a table with some input and select fields in a row. I want to check if all input and select fields of an row have a value. This is how I would think to do that, but do I have to use closest and find? I think this is not optimal.

HTML

<table>
    <tr>
        <td><select><option></option><option>Select anything</option></td>
        <td><input type="text" name="field1"></td>
        <td><input type="text" name="field2"></td>
    </tr>
    <tr>
        <td><select><option></option><option>Select something</option></td>
        <td><input type="text" name="field3"></td>
        <td><input type="text" name="field4"></td>
    </tr>
</table>

JS

'change #table input, change #table select': function(event) {
  var $this = $(event.currentTarget),
      $row  = $this.closest('tr'),
      $elements = $row.find('input, select');

  var empty = false;
  $elements.each(function(index) {
    if (!$(this).val()) empty = true;
  });

  if (empty)
    console.log('some value is missing')
  else {
    console.log('valide');
    // do something with values
  }
}

There is a table with some input and select fields in a row. I want to check if all input and select fields of an row have a value. This is how I would think to do that, but do I have to use closest and find? I think this is not optimal.

HTML

<table>
    <tr>
        <td><select><option></option><option>Select anything</option></td>
        <td><input type="text" name="field1"></td>
        <td><input type="text" name="field2"></td>
    </tr>
    <tr>
        <td><select><option></option><option>Select something</option></td>
        <td><input type="text" name="field3"></td>
        <td><input type="text" name="field4"></td>
    </tr>
</table>

JS

'change #table input, change #table select': function(event) {
  var $this = $(event.currentTarget),
      $row  = $this.closest('tr'),
      $elements = $row.find('input, select');

  var empty = false;
  $elements.each(function(index) {
    if (!$(this).val()) empty = true;
  });

  if (empty)
    console.log('some value is missing')
  else {
    console.log('valide');
    // do something with values
  }
}
Share Improve this question asked Feb 25, 2016 at 12:55 user3142695user3142695 17.4k55 gold badges200 silver badges375 bronze badges 1
  • I think I would put all input or select elements of a row in the same class and then query them by class. – neuhaus Commented Feb 25, 2016 at 13:08
Add a ment  | 

3 Answers 3

Reset to default 2

There are really two questions here:

  1. Most optimal method to select all inputs in a table row
  2. Ensure all the inputs have a value

For the first question there is a subliminal side to that. Ensure that it IS an input and then select it within the context of the current row of the changed input.

First off, jQuery uses the Sizzle (https://sizzlejs./) engine under the covers for selection. One thing to be aware of is the "right to left" processing of the selector string by that engine.

Thus the most optimal selection is somewhat browser specific but the fastest way to select is an ID followed in modern browsers by a class. Some older browsers do not select by class as well but let's leave that for your research.

Selection: Bad way to do stuff

So given that, let's look at a plex selector that you might use:

'div.mycontainer div.mytablecontainer>table#mytable.mytableclass tr td select, div.mycontainer div.mytablecontainer>table#mytable.mytableclass tr td input'

First off DO NOT USE THAT. Now to explore why not: Remember we talked about the "right to left" selector processing? For discussion let us narrow down out selector to the last part:

"div.mycontainer div.mytablecontainer>table#mytable.mytableclass tr td input"

What this does then in starting on the right:

  1. "find all the inputs in the DOM",
  2. use that list of those inputs, "find all the inputs in a td element
  3. use those td elements, find all those in a tr
  4. find all those tr in a .mytableclass element
  5. find all those in an element with an id of mytable (remember this ID MUST be unique)
  6. Now keep going, find that single element id that is a table element
  7. That is an immediate child of an element with classmytablecontainer
  8. That is a DIV element div
  9. That is a child of an element with class mycontainer
  10. That is a DIV element div

Whew that's a lot of work there. BUT we are NOT DONE! We have to do the same thing for the OTHER selector in there.

Selection: Better way to do stuff

NOW let's do this better; first off let's leverage the modern browser class selector by adding a class to all our "scoped" inputs - things we want to check for entry.

<input class="myinput" />

It does really need a type="" attribute but ignore that for now. Let's use that.

$('#mytable').find('.myinput');

What this does is:

  1. Select the element with ID of 'mytable' which is the FASTEST selector in all browsers; we have already eliminated those 47 other tables in our DOM.
  2. Find all the elements with a class of class="myinput"; within that table; in modern browsers this is also very fast

DONE. WOW! that was SO much less work.

Side note on the .find() instead of "#mytable input"

Remember our right to left once again? Find all inputs in the DOM, then narrow to those inputs we found that are in that table NO STOP THAT right now.

Or (better likely) "#mytable .myinput"

SO our "rules" of selecting a group of elements are:

  1. Use an ID to limit scope to some container if at all possible
  2. Use the ID by itself NOT part of a more plex selector
  3. FIND elements within that limited scope (by class if we can)
  4. Use classes as modern browsers have great selection optimization on that.
  5. When you start to put a space " " or ">" in a selector be smart, would a .find() or .children() be better? In a small DOM perhaps maintenance might be easier, but also which is easier to understand in 4 years?

Second question: not specific but still there

You cannot simply globally use !$(this).val() for inputs. For a check box that is invalid. What about radio buttons? What about that <input type="button" > someone adds to the row later? UGH.

SO simply add a class to all "inputs" you DO wish to validate and select by those:

<input type="text" class="validateMe" />
<select class="validateMe" >...

Side note you MIGHT want to sniff the TYPE of the input and validate based upon that: How to get input type using jquery?

EDIT: Keep in mind your validation input MIGHT have a "true/false" value so then this might fail: !$(this).val() (radio buttons, checkbox e to mind here)

Some code and markup:

<table id="mytable">
  <tr>
    <td>
      <select class="myinput">
        <option></option>
        <option>Select anything</option>
      </select>
    </td>
    <td>
      <input class="myinput" type="text" name="field1" />
    </td>
    <td>
      <input class="myinput" type="text" name="field2" />
    </td>
  </tr>
  <tr>
    <td>
      <select class="myinput">
        <option></option>
        <option>Select something</option>
      </select>
    </td>
    <td>
      <input class="myinput" type="text" name="field3" />
    </td>
    <td>
      <input class="myinput" type="text" name="field4" />
    </td>
  </tr>
</table>
<div id="results">

</div>

probably NOT want a global (namespace the "selectors")

var selectors = '.myinput';
$('#mytable').on('change', selectors, function(event) {
  var $this = $(event.currentTarget),
    $row = $this.closest('tr'),
    $elements = $row.find(selectors);
  var $filledElements = $elements.filter(function(index) {
    return $(this).val() || this.checked;
  });

  var hasEmpty = $filledElements.length !== $elements.length
  var rowIndex = $row.index();
  $('#results').append("Row:" + rowIndex + " has " + $filledElements.length + ' of ' + $elements.length + ' and shows ' + hasEmpty + '<br />');
  if (hasEmpty)
    console.log('some value is missing');
  else {
    console.log('valide');
    // do something with values
  }
});

AND something to play with: https://jsfiddle/MarkSchultheiss/fqadx7c0/

If you're only selecting on particular element with knowing which parent to select with, you should try using .filter() to filter out only element that did't have a value like following :

$('button').click(function() {

    var h = $('table :input').filter(function() {
       return $(this).val() == "" && $(this);
    }).length;

    alert(h);

});

DEMO

I did this plunk

https://plnkr.co/edit/q3iXSbvVWEQdLSR57nEi

$(document).ready(function() {
  $('button').click(function() {
    var table = $('table');
    var rows = table.find('tr');
    var error = 0;

    for (i = 0; i < rows.length; i++) {
      var cell = rows.eq(i).find('td');
      for (a = 0; a < cell.length; a++) {
        var input = cell.eq(a).find(':input');

        if (input.val() === "") {
          input.css("border", "solid 1px red");
          error++;
        } else {
          input.css("border", "solid 1px rgb(169, 169, 169)");
        }
      }
    } 

    if (error > 0){
      alert('Errors in the form!')
      return false;
    } else {
      alert('Form Ok!')
      return true;
    }
  })
})

Simple Jquery validation, searching all the inputs (including selects), if it's null, increment the error counter and change class. If the error counter is > 0, alert error and return false;

Maybe isn't the best solution, but it sure can help get started.

本文标签: javascriptCheck if all inputselect fields of a table row have valuesStack Overflow