Array.prototype.filter does not work as expected

Asked

Viewed 89 times

1

I am trying to validate fields using the Array.prototype.filter() method, but it does not seem to have an effect:

<script>
    function isEmpty() {
        document.getElementById("submit").disabled = 
            Array.prototype.filter.call(
                Array.prototype.slice.call(
                    document.getElementsByClassName("input")),
                        function(input) {
                            input.value != "";
                        });
    }
</script>
<form>
    <input class="input" onkeydown="isEmpty()" onkeyup="isEmpty()">
    <input class="input" onkeydown="isEmpty()" onkeyup="isEmpty()">
    <input class="input" onkeydown="isEmpty()" onkeyup="isEmpty()">
    <input class="input" onkeydown="isEmpty()" onkeyup="isEmpty()">
    <button id="submit" disabled>
</form>

What was supposed to occur is the button is enabled only when all fields are filled, but that’s not what happens.

2 answers

2


Three things you must change in your code:

#1 - the filter method must have inside the callback function a return. In other words, instead of just input.value != ""; you must have return input.value != "";

#2 - when you use the filter method you have to read the property .length to know if there are values within the result. Like hugomg referred to an empty validated array as true, then you must use .length to know if the actual array is empty.

#3 - when you use Array.prototype.filter.call(lista, callback); you no longer need to use the .slice. You can remove that line.

So the corrected and more organized code could be like this:

function isEmpty() {
    var submit = document.getElementById("submit");
    var inputs = document.getElementsByClassName("input");
    var empty =  Array.prototype.filter.call(inputs, function (input) {
        return input.value.trim() == "";
    });
    submit.disabled = !!empty.length;
}

jsFiddle: http://jsfiddle.net/c0vy3fgc/

  • About the Return, I forgot to put here in the post. Already the .slice, would not be necessary, since the getElementsByClassName returns an array-like and the .filter works with arrays?

  • @Patrick the Array.prototype.filter will treat this list of DOM nodes as an array and hence Slice is not required.

2

The filter method returns a list and Javascript lists always count as "true" in a Boolean context (including the empty list).

if( [] ){
    console.log("Olá!");
}else{
    connsole.log("Esse else nunca roda");
}

However, I think the method every fits better into what you want to do than the filter.

  • Wow, but [] == false can’t true?

  • Never trust the operator of == from Javascript :) He makes some conversions of crazy types and almost always it is better to use the === instead of him.

  • I put the every, but now it enables the button the first entry and even if I delete, it is still enabled. Is there any problem with the slice or getElementsByClassName?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.