Why JQuery (!) not assignment returning only false

Viewed 82

I am working on a project and have a lot of boolean fields. I want these fields to return boolean value(1 or 0). I don't know if its an embarrassing question but I cant change the value of the input by not (!) assignment in jQuery. It works for 2 clicks and after that it always returns false. In first click since the value of the hidden input is empty it returns true, on second click it returns false as !true=false. After that on all the clicks it only returns false.

My Html

<div class="col-md-4">
  <label>Required?</label>
  <input type="checkbox" name="" class="form-control required_field">
  <input type="hidden" name="field_required[]" value="">
</div>

My Jquery

$('div').on('click', '.required_field', function() {
  let v = !($(this).siblings('input').val());
  $(this).siblings('input').val(v);
  console.log($(this).siblings('input').val());
});

It works with ternary operators and if else, if I compare with values as:

$('.div').on('click','.required_field',function(){
     $(this).siblings('input').val(($(this).siblings('input').val()==1)?0:1);
     console.log($(this).siblings('input').val());
});

Or

$('.up-field-sec').on('click','.required_field',function(){
        let v = $(this).siblings('input').val();
        $(this).siblings('input').val((!$(this).siblings('input').val() || v==0)?1:0);
        console.log($(this).siblings('input').val());
    });

I find it very strange how can it be !false = false ?? What am I missing here? This is bugging me. I would be very glad if anyone can explain this to me. Thank you in advance.

Here is the Jsfiddle of the code.

2 Answers

The issue is because any non-empty string coerces to true, even if it contains the word "false", or the number "0". As such, !"false" is always false.

To fix this you need to use !!. The right ! converts the string to a boolean and the left ! operator inverts that result.

$('div').on('click', '.required_field', function() {
  let v = !!$(this).siblings('input').val();    
  $(this).siblings('input').val(v);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col-md-4">
  <label>Required?</label>
  <input type="checkbox" name="" class="form-control required_field">
  <input type="hidden" name="field_required[]" value="">
</div>

Thank you all for helping me, you guys rock!

I did some digging and this is the conclusion I came up to:

Here what is happeing in the code above. Every time when value of the input is taken from a HTML element it is a string. The value in the first click will be an empty string and (!'') (just like if empty is false !empty is true) will be true which is same as !0 which is true. In second click the value of the input will be "true" (a string) and !'true' (value is not empty so it will return false) is false. Till then everything looks perfect. After this every other clicks will return false string value not(!) operator will return false because the value is not empty.

To understand better

//first click
console.log('first click');
let v = '';
console.log('!v is: '+!v);
console.log('typeof !v is: '+typeof(!v));
console.log(!v);
v = !v;

//second click
console.log('Second click');
v='true';
console.log('!v is: '+!v);
console.log('typeof !v is: '+typeof(!v));
console.log(!v);

//third click
console.log('Third click');
v='false';
console.log('!v is: '+!v);
console.log('typeof !v is: '+typeof(!v));
console.log(!v);

//Fourth click
console.log('Fourth click');
v='false';
console.log('!v is: '+!v);
console.log('typeof !v is: '+typeof(!v));
console.log(!v);

To overcome this and preserve the boolean value:

$('div').on('click', '.required_field', function() {
  let v = !($(this).siblings('input').val()==='true');
  $(this).siblings('input').val(v);
  console.log($(this).siblings('input').val());
});

I got help from: How can I convert a string to boolean in JavaScript?

Related