Home > Enterprise >  Checking Every Input and Disabling a Button
Checking Every Input and Disabling a Button

Time:01-25

I have a button and I want to disable it when any of the input field is empty.

Below is not working. If all input fields are empty, it returns true which is correct. But if only one input field is filled, it returns false which is not correct. It should return true until all fields are filled.

<Button
  disabled={Object.values(values).every(x => x === "")}
  onClick={handleSubmit}>
  Submit
</Button>

Below is working correctly but ESlint throws an error.

<Button
  disabled={Object.values(values).every(function () {
    for (let key in values) {
      if (values[key] === "")
        return true;
    }
    return false;
  })}
  onClick={handleSubmit}>
  Submit
</Button>

ESlint error:

for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array no-restricted-syntax

How can I correct disabled functionality?

values={{ testData1: '', testData2: '', testData3: ''}}

CodePudding user response:

Change,

disabled={Object.values(values).every(x => x === "")}

To:

disabled={Object.values(values).some(x => x === "")}

Reason for the change:

The every method checks whether all elements in the array pass the test.

So in your case, using every checks if all the value is empty, and as you told that initial state it was working (on load) because on initial render all the value will be empty and hence this test pass (and returns true) but once you have any value it will return false because it has one of the value.

Whereas Some on the other hand, checks whether at least one of the element in the array pass the test.

Here we need to use some because it will check whether at least one of the value is empty or not. It will return true till all the values are filled. If all the fields are filled then it will return false.

More on difference between every and some

CodePudding user response:

Object.values(values) returns an array, so you can iterate over it with for..of.

Below code is equivalent to yours (assuming values is a flat object) but uses for..of instead of for..in, and thus should look fine to ESlint eyes:

<Button
  disabled={function () {
    for (const val of Object.values(values)) {
        if (val === "")
            return true;
    }
    return false;
    }}
  onClick={handleSubmit}>
  Submit
</Button>

Edit: this snippet should work for nested objects:

<Button
    disabled={
        function findEmpty(arg) {

            for (i in arg) {
                if (typeof arg[i] === 'object') {
                    return findEmpty(arg[i]);
                }

                if (arg[i] == "") {
                    return true;
                }
            }
            return false
        }
        findEmpty(values);
    }
    onClick={handleSubmit}>
    Submit
</Button>
  •  Tags:  
  • Related