Search code examples
javascriptjqueryobject

Prevent checkbox if doesn't meet the condition


I have a list of checkboxes, inside the input element I have added 2 custom attributes

The checkbox is disabled by default, the idea is that if the svcjurisdiction object matches the value of rcpjurisdiction then is enabled, but it isn't working.

$('input[type=checkbox]').each(function() {
    var svcjurisdiction = $(this).attr("data-svcjurisdiction").split(',');
    var rcpjurisdiction = $(this).attr("data-rcpjurisdiction");

    console.log(svcjurisdiction)
    if (svcjurisdiction.includes(rcpjurisdiction)) {
        console.log(rcpjurisdiction)
        $(this).attr("disabled", false)
    }

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="services" value="13301686-3218159" data-rcpjurisdiction="Guernsey" data-svcjurisdiction="SCPB - LON, Guernsey" type="checkbox" title="Text to show" checked disabled/>


Solution

  • One approach is below, with explanatory comments in the code:

    // selecting each <input> of type=checkbox, iterating over the collection using the each() method:
    $('input[type=checkbox]').each(function() {
      // retrieving a reference to the named attributes, converting the String of
      // "data-svcjurisdiction" to a two-part Array, using String.prototype.split():
      let svcjurisdiction = $(this).attr("data-svcjurisdiction").split(',');
      let rcpjurisdiction = $(this).attr("data-rcpjurisdiction");
    
      // here we update the 'disabled' property of the current <input> element; we use Array.prototype.some()
      // to test whether any of the Array-elements includes the string held in the rcpjurisdiction variable;
      // as Array.prototype.some() returns a Boolean to indicate that matches were found (true) or not-found
      // (false), we invert that property using the not-operator to disable or enable the element:
      $(this).prop('disabled', !svcjurisdiction.some((svc) => svc.includes(rcpjurisdiction)));
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <input class="services" value="13301686-3218159" data-rcpjurisdiction="Guernsey" data-svcjurisdiction="SCPB - LON, Guernsey" type="checkbox" title="Text to show" checked disabled/>
    <!--
      adding a second <input> deliberately ensuring its "data-rcpjurisdiction" attribute-value is
      not present in the "data-svcjurisdiction" attribute:
    -->
    <input class="services" value="13301686-3218159" data-rcpjurisdiction="Jersey" data-svcjurisdiction="SCPB - LON, Guernsey" type="checkbox" title="Text to show" checked disabled/>

    The problem with your original code is

    $('input[type=checkbox]').each(function() {
        var svcjurisdiction = $(this).attr("data-svcjurisdiction").split(',');
        var rcpjurisdiction = $(this).attr("data-rcpjurisdiction");
    
        // Array.prototype.includes() requires an exact
        // match, unfortunately after splitting on ','
        // the Array of strings included leading whitespace,
        // which prevented a successful match:
        if (svcjurisdiction.includes(rcpjurisdiction)) {
    
            $(this).attr("disabled", false)
        }
    
    });
    

    Incidentally, this can be accomplished quite easily with just plain JavaScript if you wish to do so:

    const D = document,
          get = (selector, context = D) => context.querySelector(selector),
          getAll = (selector, context = D) => [...context.querySelectorAll(selector)];
    
    // selecting each <input> of type=checkbox, iterating over the collection using the Array.prototype.forEach() method:
    getAll('input[type=checkbox').forEach(
      (elem) => {
        // using destructuring assignment to retrieve the two custom data-* attributes from
        // the elem.dataset Object:
        let {rcpjurisdiction, svcjurisdiction} = elem.dataset,
    
        // we split the data-svcjurisdiction attribute-value on the comma character,
        // using String.prototype.split() to generate an Array and we then iterate
        // over that Array using Array.prototype.map() to create a new Array:
        svc = svcjurisdiction.split(',').map(
          // we pass in the current Array of the Array of Strings ('str'),
          // and in the function body we use String.prototype.split() to
          // remove leading/trailing whitespace:
          (str) => str.trim()
        );
        // we then set the disabled property of the element to be the inverse
        // of the Boolean returned from Array.prototype.includes(), which returns
        // true of the string is included and false if it is not (we invert this
        // because you wish to enable the <input> if there is a match and we're
        // working with the disabled property):
        elem.disabled = !svc.includes(rcpjurisdiction);
      });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <input class="services" value="13301686-3218159" data-rcpjurisdiction="Guernsey" data-svcjurisdiction="SCPB - LON, Guernsey" type="checkbox" title="Text to show" checked disabled/>
    <!--
      adding a second <input> deliberately ensuring its "data-rcpjurisdiction" attribute-value is
      not present in the "data-svcjurisdiction" attribute:
    -->
    <input class="services" value="13301686-3218159" data-rcpjurisdiction="Jersey" data-svcjurisdiction="SCPB - LON, Guernsey" type="checkbox" title="Text to show" checked disabled/>

    References: