3

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.

wupendra
  • 76
  • 8

2 Answers2

1

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>
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • Thank yo for the solution but I am curious why `!true` returned `false` on the second click? – wupendra Jul 30 '20 at 10:43
  • On the first click the value was an empty string, which coerces to `false` correctly. – Rory McCrossan Jul 30 '20 at 10:47
  • Thank you for the clearification. I understand the problem. – wupendra Jul 30 '20 at 10:48
  • now after adding `!!` it remains true after the second click. – wupendra Jul 30 '20 at 11:49
  • Indeed. If all you're trying to do is store the boolean state of the `checked` flag in the textbox (which itself is a little redundant), just use the `checked` property directly: `$(this).siblings('input').val(this.checked);` – Rory McCrossan Jul 30 '20 at 13:23
  • I wanted to send the checked propertery as a definite boolean values (0,1) so that I can mass assign the database according to value without thinking much about filtering the data. I have been using `$(this).siblings('input').val((!v || v==0)?1:0);` for the expected result. But I was only curious about why the value from an input definite (true, flase) can't be inverted using not`(!)` operator like many other languages with JQuery val() property. One thing is sure that the val property is fetching the value as "true", "false". For integer there is `parseInt` but for boolean there isnt such. – wupendra Jul 30 '20 at 13:52
0

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?

wupendra
  • 76
  • 8