0

Let's say I have several date inputs, which I'd like to change color after user input. With jQuery I could do:

$('input[type="date"]').on('change', function() {
  var el = $(this).val();
  if (el === '') {
    $(this).css('color', '#9c9c9c');
  } else {
    $(this).css('color', '#000000');
  }
})
input[type="date"] {
  color: #9c9c9c;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="date" placeholder="MM/DD/YYYY">
<input type="date" placeholder="MM/DD/YYYY">

But, when I try to achieve the same with plain JS (document.querySelector() or document.querySelectorAll().forEach()), I'm unable to. I can only make the first input work with the document.querySelector() approach:

var el = document.querySelector('input[type="date"]');
el ? el.onchange = function() {
  if (this.value === '') {
    this.style.color = '#9c9c9c';
  } else {
    this.style.color = '#000000';
  }
} : "";

//tried also
/*document.querySelectorAll('input[type="date"]').forEach(function() {
   this.onchange = function() {
    if (this.value === '') {
      this.style.color = '#9c9c9c';
    } else {
      this.style.color = '#000000';
    }
  }
});*/
input[type="date"] {
  color: #9c9c9c;
}
<input type="date" placeholder="MM/DD/YYYY">
<input type="date" placeholder="MM/DD/YYYY">

Based on this excellent SO answer, I'm also using a ternary operator to check if the element exists in the DOM first, otherwise I'm getting error on pages where the inputs are not in the DOM.

How to achieve this with plain JS & avoiding null errors on non-existent DOM elements?

Syden
  • 7,856
  • 5
  • 22
  • 39
  • 1
    `document.querySelector('input[type="date"]')` gives you the first Element of that kind. You would have to use `document.querySelectorAll('input[type="date"]')` and loop over the Array it returns. Vanilla JS is not jQuery. – StackSlave Mar 29 '18 at 01:59
  • 1
    @PHPglue Not quite. `querySelectorAll` returns an array-like object (a `NodeList`), not an actual `Array` (so even in this case, `forEach` would not work) – Tibrogargan Mar 29 '18 at 02:02
  • Do `var ary = [].slice.call(document.querySelectorAll('input[type="date"]'))` then. – StackSlave Mar 29 '18 at 02:09
  • Considering both `for` & `forEach` solutions work, any performance reason why to use one over the other? Tested here https://jsfiddle.net/Syden/a16aru5m/46/ Also same question with `.onchange` vs `addEventListener`. Thank you. – Syden Mar 29 '18 at 13:20

3 Answers3

1

I think your problem is how you are looping the elements of the query:

Works fine with a simple for

Or change to call it like this:

[].forEach.call(listElements, function(element) {
    //Add event onchange
});

I changed the color to red to a better visualization

var listElements = document.querySelectorAll('input[type="date"]');

[].forEach.call(listElements, function(element) {
  
});


for (var i in listElements) {
    element = listElements[i];
    element.onchange = function() {
        if (this.value === '') {
            this.style.color = 'red';
        } else {
            this.style.color = '#000000';
        }
    }
}
input[type="date"] {
  color: red;
}
<input type="date" placeholder="MM/DD/YYYY">
<input type="date" placeholder="MM/DD/YYYY">
<input type="date" placeholder="MM/DD/YYYY">
Matheus Cuba
  • 1,886
  • 1
  • 18
  • 27
1

when you using document.querySelectorAll, it always return an array. use forEach for loop all item in array (array can be empty but it is empty array). You can using addEventListener for listening event onchange, and this is example:

var inputs = document.querySelectorAll('input[type="date"]');
inputs.forEach (function (item) {
  item.addEventListener('change', function () {
    this.classList.add("red");
  })
})
.red {
  background: red;
}
<input type="date">
<input type="date">
<input type="date">
Lê Phi
  • 442
  • 2
  • 9
1

at this.onchange = function()
this would be window, not each element

so simply replace this like :

document.querySelectorAll('input[type="date"]').forEach(function(element) {
   element.onchange = function() {
      if (element.value === '') {
          element.style.color = '#9c9c9c';
      } else {
          element.style.color = '#000000';
      }
  }
});

You can learn more from this post : How does the “this” keyword work?

Hikarunomemory
  • 3,902
  • 2
  • 7
  • 19