-1

I need to get the value of the checked checkbox (only one is allowed to be checked at a time), and I have this verbose code to do so:

if (!checkboxSelected) {
    return;
}

if($("#ckbx_produceusage").is(':checked')) {
    rptval = $('#ckbx_produceusage').val();
}
else if($("#ckbx_deliveryperformance").is(':checked')) {
    rptval = $('#ckbx_deliveryperformance').val();
}
else if($("#ckbx_fillrate").is(':checked')) {
    rptval = $('#ckbx_fillrate').val();
}
else if($("#ckbx_pricecompliance").is(':checked')) {
    rptval = $('#ckbx_pricecompliance').val();
}
setEmailAndGenerateValsForUnitReportPair(unitval, rptval);

Is there a way I can make this code less verbose without making it ungrokkable? I thought of dynamically adding a class to the checkbox that is checked, and then removing it from any that previously had that class added, and then getting the rptval based on which one is currently decorated with that class. That seems a bit smelly or Rubegoldbergesque, though, so am looking for a better solution.

UPDATE

For T.J. Crowder, here is the HTML (Razor/ASP.NET MVC style):

@foreach (var rpt in reports)
{
    @* convert id to lowercase and no spaces *@
    var morphedRptName = @rpt.report.Replace(" ", string.Empty).ToLower();
    <input class="ckbx leftmargin8" id="ckbx_@(morphedRptName)" type="checkbox" value="@rpt.report" />@rpt.report
}
B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862

5 Answers5

1

JQuery collections are filterable, so I'd suggest using the following:

// get value of first checked checkbox
var rptval = $(
   "#ckbx_produceusage,"+
   "#ckbx_deliveryperformance,"+
   "#ckbx_fillrate,"+
   "#ckbx_pricecompliance"
).filter(':checked').first().val();

Note: The .first() may even be unnecessary since .val() gets the value of the first element in the collection. Left in for legibility's sake.

amphetamachine
  • 27,620
  • 12
  • 60
  • 72
1
$(function()
{
...
// IF (these are the only elements that id starts with ckbx_) THEN
    rptval = $('[id^=ckbx_]').filter(':checked').val();
// ELSE
    // this syntax is more maintainable than $('#ckbx_produceusage, #ckbx_fillrate, ... selectors à la queue');
    rptval = $('#ckbx_produceusage').add('#ckbx_fillrate').add('#ckbx_deliveryperformance').add('#ckbx_pricecompliance').filter(':checked').val();
// FI
...
});
Salathiel Genese
  • 1,639
  • 2
  • 21
  • 37
0

Without changing your HTML, you can at least avoid repeating yourself by using a loop:

["#ckbx_produceusage", "#ckbx_deliveryperformance", "#ckbx_fillrate", "#ckbx_pricecompliance"].some(function(sel) {
    var e = $(sel);
    if (e.is(":checked")) {
        rptval = e.val();
        return true;
    }
});
setEmailAndGenerateValsForUnitReportPair(unitval, rptval)

You could probably change your HTML such that the initial array could be a query rather than a hardcoded list of ID selectors.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

You also need to account for the situation where none are checked. Never assume something is set.

function getValue(checkBoxes)
{
    for ( var i = 0; i < checkBoxes.length; i++ )
    {
        var name = "#ckbx_" + checkBoxes[ i ];

        if ( $( name ).is( "checked" ) ) return $( name ).val();
    }

    //None were checked
    return null; //Should throw exception
}

rptval = getValue( [ "produceusage", "deliveryperformance", "fillrate", "pricecompliance" ] );
Don Rhummy
  • 24,730
  • 42
  • 175
  • 330
  • id declare a variable `length` and assign it to `checkboxes.length` and add the new variable in the for loop so the length isn't calculated every time – Abdul Ahmad Apr 26 '16 at 16:32
  • @AbdulAhmad You're misunderstanding how that works. The length is not compiled every time through the loop. – Don Rhummy Apr 26 '16 at 17:22
  • i said calculated not compiled. but i guess its not recalculated every time according to some other questions – Abdul Ahmad Apr 26 '16 at 17:25
0

Try using .each()

  $("input[type='checkbox']").each(function() {
    var rptval = 0;
    if ($(this).is(":checked")) {
      rptval = 1;
    }
    setEmailAndGenerateValsForUnitReportPair(unitval, rptval);
  });
johnniebenson
  • 540
  • 3
  • 9