Create Multiple Checkboxes Instead of a Multiple-Select in your Views

This article is also available in the following languages:
By joshuamcfarren
From a usablitiy stand point, multiple-select boxes are a nightmare. Forget to hold down the modifier key when adding an option and you loose all your selections. When the number of options are managable, multiple checkboxs are a better choice for average users. This functionality is coming to cake in future versions but you can have it now with this helper.
Save this as habtm.php in app/views/helpers
<?php
class HabtmHelper extends HtmlHelper {
    
    
/**
     * Returns a list of checkboxes.
     *
     * @param string $fieldName Name attribute of the SELECT
     * @param array $options Array of the elements (as 'value'=>'Text' pairs)
     * @param array $selected Selected checkboxes
     * @param string $inbetween String that separates the checkboxes.
     * @param array $htmlAttributes Array of HTML options
     * @param  boolean $return         Whether this method should return a value
     * @return string List of checkboxes
     */
    
function checkboxMultiple($fieldName$options$selected null$inbetween null$htmlAttributes null$return false) {
        
$this->setFormTag($fieldName);
        if (
$this->tagIsInvalid($this->model$this->field)) {
            if (isset(
$htmlAttributes['class']) && trim($htmlAttributes['class']) != "") {
                
$htmlAttributes['class'] .= ' form_error';
            } else {
                
$htmlAttributes['class'] = 'form_error';
            }
        }
        if (!
is_array($options)) {
            return 
null;
        }    
        if (!isset(
$selected)) {
            
$selected $this->tagValue($fieldName);
        }
        foreach(
$options as $name => $title) {
            
$optionsHere $htmlAttributes;
            if ((
$selected !== null) && ($selected == $name)) {
                
$optionsHere['checked'] = 'checked';
            } else if (
is_array($selected) && array_key_exists($name$selected)) {
                
$optionsHere['checked'] = 'checked';
            }
            
$optionsHere['value'] = $name;
            
$checkbox[] = "<li>" sprintf($this->tags['checkboxmultiple'], $this->model$this->field$this->parseHtmlOptions($optionsHere), $title) . "</li>\n";
        }
        return 
"\n" sprintf($this->tags['hiddenmultiple'], $this->model$this->fieldnull$title) . "\n<ul class=\"checkboxMultiple\">\n" $this->output(implode($checkbox), $return) . "</ul>\n";
    }
    
}
?>

Add this snip of css to your stylesheet and adjust the li width to your taste
ul.checkboxMultiple {
    margin:0;
    padding:0;
    list-style-type:none;
    }
ul.checkboxMultiple li {
    display:block;
    float:left;
    width: 220px;
    margin: 0 8px 0 0;
    }

And add these tag templates to app/config/tags.ini.php
; Tag template for an input type='hidden' tag.
hiddenmultiple = "<input type="hidden" name="data[%s][%s][]" %s/>"

; Tag template for a input type='checkbox ' tag.
checkboxmultiple = "<input type="checkbox" name="data[%s][%s][]" %s/>%s"

Then you can use the new helper exactly the same way as $html->selectTag(...) just change your method call to $habtm->checkboxMultiple(..) instead.

Acknowledgment: This is based off code by MrRio in the Trac system:
https://trac.cakephp.org/ticket/1260

Comments

  • Posted 03/17/10 04:41:35 PM
    if you get this error, it's probably because you're using 1.2.x

    here's the solution.

    replace the setFormTag line with this.

    $this->_initInputField($fieldName);

    and you're done.
  • Posted 06/24/09 10:15:02 PM
    with the new 1.2 multiple=>checkbox magic, the output is fairly ugly. a long list of checkboxes, no scrolling, not lined up with the other input fields, etc. here are some simple bits of code that make it much nicer looking.

    in the view, add:
    $html->tags['checkboxmultiplestart'] = '<div class="checkboxmultiple">';
    $html->tags['checkboxmultipleend'] = '</div>';
    or i guess you could use $this->HtmlHelper->tags in the controller. that will put a div wrapper around the list of checkboxes so you can format it.

    then add a css blob to your css file, or inline, or whatever:
    div.checkboxmultiple {
        clear: none;
        height: 6em;
        overflow: auto;
        max-width: 250px;
        border: 1px solid gray;
    }
    of course those values might need to be tweaked for your site.

  • Posted 06/08/09 02:31:12 PM
    Let cake do this automatically now by adding the following code to your view:
    echo $form->input('Model', array('multiple'=>'checkbox'));
  • Posted 12/12/08 09:25:13 PM
    I dunno but is
    'checked'=>($this->data["Model"]["id"][$id] == 1 ? 'checked' : false
    really OK?

    If I pr($this->data), the HABTM array is like:
    [Model][0][id] [Model][1][id]

    In my case, list is like
    $options = $this->Model1->Model->find('list');
    tho.
  • Posted 07/16/08 01:57:25 AM
    I have a code in controller:

    foreach($this->data as $user){
    foreach($user['user_id'] as $userid){
    // If User already assigned then Update else Insert
    if($this->Project->query("SELECT id,user_id,project_id FROM tts_users_projects ProjectUser WHERE user_id = '".$userid."' AND project_id = '".$id."'")){
    //$this->Project->query("UPDATE tts_users_projects SET user_id = '".$userid."' AND project_id = '".$id."' WHERE project_id = ".$id." AND user_id = ".$userid);
    }else{
    if (!$this->Project->query("INSERT INTO tts_users_projects(`user_id`,`project_id`) VALUES ('".$userid."','".$id."')")){
    $error[] = $user; // fetch Error(s)
    }
    }

    }
    }

    I dont understand why when I save data, and forexample I have checkboxes in the sequence below:
    [ ] Waqar
    [X] Mohsin
    [X] Mubashir
    [ ] Test

    if i check the "Test" it will be saved, but if I check "Waqar" which is above the checked checkboxes, it doesn't save.

    Any idea? Its confusing me.
  • Posted 07/16/08 01:57:20 AM
    I have a code in controller:

    foreach($this->data as $user){
    foreach($user['user_id'] as $userid){
    // If User already assigned then Update else Insert
    if($this->Project->query("SELECT id,user_id,project_id FROM tts_users_projects ProjectUser WHERE user_id = '".$userid."' AND project_id = '".$id."'")){
    //$this->Project->query("UPDATE tts_users_projects SET user_id = '".$userid."' AND project_id = '".$id."' WHERE project_id = ".$id." AND user_id = ".$userid);
    }else{
    if (!$this->Project->query("INSERT INTO tts_users_projects(`user_id`,`project_id`) VALUES ('".$userid."','".$id."')")){
    $error[] = $user; // fetch Error(s)
    }
    }

    }
    }

    I dont understand why when I save data, and forexample I have checkboxes in the sequence below:
    [ ] Waqar
    [X] Mohsin
    [X] Mubashir
    [ ] Test

    if i check the "Test" it will be saved, but if I check "Waqar" which is above the checked checkboxes, it doesn't save.

    Any idea? Its confusing me.
  • Posted 04/12/08 03:27:59 PM
    In Cake 1.2 I find that with an options variable generated from Model->find('list'):

    Controller Class:

    <?php 
    $options 
    $this->Model->find('list');
    $this->set('options'$options);
    ?>

    View Template:


    <?php
    foreach ($options as $id=>$label) {
        echo 
    $form->input("Model.id.$id"
            array(
                
    'label'=>$label,
                
    'type'=>'checkbox',
                
    'checked'=>($this->data["Model"]["id"][$id] == 'checked' false)
                )
            );
    }
    ?>

    Works fine if you'd rather not use yet another helper.
    • Posted 11/08/08 09:36:07 PM
      I tried this because I wanted to add html links beside my checkboxes.
      I can't use input('Post.Tag', array('type'=>'select', 'multiple'=>'checkbox', 'options'=>$tags, 'label'=>'Tags:'));?> since it automatically generates the checkboxes and doesn't allow me to add anything beside them.

      Anyway, I think there's something wrong with the view code if used on an edit view.

      View Template:


      <?php
      foreach ($options as $id=>$label) {
          echo 
      $form->input("Model.id.$id"
              array(
                  
      'label'=>$label,
                  
      'type'=>'checkbox',
                  
      'checked'=>($this->data["Model"]["id"][$id] == 'checked' false)
                  )
              );
      }
      ?>

      It does not display the already checked checkboxes and it also doesn't pass the correct $this-data['Field'] data to the controller when an edit is submitted.

      I had to modify it to the ff to make it work

      View Template:


      <?php
      foreach ($options as $id=>$label) {
                  
      $check false;

                  
      //Determine if the checkbox is already checked or not
                  
      foreach($this->data['Model'] as $data)
                  {
                      if(
      $data['id'] == $id) {
                          
      $check true;
                          break;
                      }
                  }

                  
      //First param is weird but it works
                  
      echo $form->input('Model.Model]['
                      array(
                          
      'label'=>$label,
                          
      'type'=>'checkbox',
                          
      'checked'=> $check,
                          
      'value' => $id
                          
      )
                      );

                  echo 
      $html->link('My link beside the checkbox','/');
              }
      ?>


      Would there be an easier way to put a link (or whatever text) that's associated with a checkbox BESIDE the checkbox without having to do the above?

      -pacfan

      In Cake 1.2 I find that with an options variable generated from Model->find('list'):

      Controller Class:

      <?php 
      $options 
      $this->Model->find('list');
      $this->set('options'$options);
      ?>

      View Template:


      <?php
      foreach ($options as $id=>$label) {
          echo 
      $form->input("Model.id.$id"
              array(
                  
      'label'=>$label,
                  
      'type'=>'checkbox',
                  
      'checked'=>($this->data["Model"]["id"][$id] == 'checked' false)
                  )
              );
      }
      ?>

      Works fine if you'd rather not use yet another helper.
  • Posted 02/01/08 10:25:30 PM
    im so sorry..

    previously, i was using cake 1.2.0.5875 pre-beta then i try it on cake 1.2.0.6311 beta and its working..

    thanx ambiguator
  • Posted 01/16/08 08:45:54 AM
    i dont know is it what you really mean or not...but why did i get a selectbox when i use

    View Template:


    <?php echo $form->input('Post.Tag', array('type'=>'select''multiple'=>'checkbox''options'=>$tags'label'=>'Tags:'));?>

    didn't we talk about checkbox ???


    i'm sorry if i was mistaken
    • Posted 01/21/08 10:35:43 AM
      Perhaps you are not on cake1.2beta?
      this exact snippet works a-ok for me.

      i dont know is it what you really mean or not...but why did i get a selectbox when i use

      View Template:


      <?php echo $form->input('Post.Tag', array('type'=>'select''multiple'=>'checkbox''options'=>$tags'label'=>'Tags:'));?>

      didn't we talk about checkbox ???


      i'm sorry if i was mistaken
  • Posted 01/05/08 05:41:04 PM
    I just noticed that multiple checkboxes can be used inherently in the current beta version of CakePHP 1.2. It can easily be used via the following method:

    View:
    <?php echo $form->input('Post.Tag', array('type'=>'select''multiple'=>'checkbox''options'=>$tags'label'=>'Tags:'));?>

    Selecting list data is a bit different in this most recent version as well.

    Model:
    <?php
    class Tag {
        
    // The column value to show in SELECT OPTION's.
        
    var $displayField 'name';
    }
    ?>

    Controller:
    <?php
    function index() {
        
    $this->set('tags'$this->Tag->find('list'));
    }
    ?>
  • Posted 01/04/08 09:39:26 AM
    I'm sure this is my stupidity, but can some explain the reason for the hidden field before the checkboxes? I get an empty array element before the actual checkbox values when I submit the form... I've removed the code creating it, but as I'm not entirely sure why its there I thought I'd better check...
    Cheers!
  • Posted 11/15/07 02:34:07 AM
    check php manual for array_search() -
    sometimes it returns 0 - which is not false, so manually check for false

    } else if (is_array($selected) && array_search($name , $selected)!==false) {
  • Posted 10/18/07 12:13:22 AM
    Hey guys,

    If your checkboxes are being selected in wierd ways (ie: if you select 3 our of 10 at random spots, after a save error the first 3 are ticket not the ones you wanted, there is a simple solution.

    Change the following line:

    } else if (is_array($selected) && array_key_exists($name, 
    $selected)) { 

    To:

    } else if (is_array($selected) && array_search($name, $selected)) {
  • Posted 08/27/07 11:32:23 AM
    I receive an amount of error messages equal to the amount of checkboxes it needs to show... although the checkboxes seem to be fine!

    The error message is:


    Notice: Uninitialized string offset: 0 in D:\TYPO3\Apache\htdocs\cake\app\views\helpers\habtm.php on line 36

    EDIT: It seems I based this bug on older code... which I don't understand because I copied it just last week. Anyway, the problem I have using the code mentioned in the article is that the checkboxes don't keep their current state when the form does not validates.

    This does seem to work for me:


    <?php
    class HabtmHelper extends HtmlHelper {
        
        
    /**
         * Returns a list of checkboxes.
         *
         * @param string $fieldName Name attribute of the SELECT
         * @param array $options Array of the elements (as 'value'=>'Text' pairs)
         * @param array $selected Selected checkboxes
         * @param string $inbetween String that separates the checkboxes.
         * @param array $htmlAttributes Array of HTML options
         * @param  boolean $return         Whether this method should return a value
         * @return string List of checkboxes
         */
        
    function checkboxMultiple($fieldName$options$selected null$inbetween null$htmlAttributes null$return false) {
            
    $this->setFormTag($fieldName);
            if (
    $this->tagIsInvalid($this->model$this->field)) {
                if (isset(
    $htmlAttributes['class']) && trim($htmlAttributes['class']) != "") {
                    
    $htmlAttributes['class'] .= ' form_error';
                } else {
                    
    $htmlAttributes['class'] = 'form_error';
                }
            }
            if (!
    is_array($options)) {
                return 
    null;
            }    
            if (!isset(
    $selected)) {
                
    $selected $this->tagValue($fieldName);
            }
            foreach(
    $options as $name => $title) {
                
    $optionsHere $htmlAttributes;
                if ((
    $selected !== null) && ($selected == $name)) {
                    
    $optionsHere['checked'] = 'checked';
                } else if (
    is_array($selected) && count($selected) >0) {
                    foreach(
    $selected as $array) {
                        if(
    $array == $name) {
                            
    $optionsHere['checked'] = 'checked';
                        }
                    }
                }
                
    $optionsHere['value'] = $name;
                
    $checkbox[] = "<li>" sprintf($this->tags['checkboxmultiple'], $this->model$this->field$this->parseHtmlOptions($optionsHere), $title) . "</li>\n";
            }
            return 
    "\n" sprintf($this->tags['hiddenmultiple'], $this->model$this->fieldnull$title) . "\n<ul class=\"checkboxMultiple\">\n" $this->output(implode($checkbox), $return) . "</ul>\n";
        }
        
    }
    ?> 
  • Posted 08/12/07 06:05:43 AM
    Using 1.2.0.5427alpha I recieved Method tagValue() is deprecated in HtmlHelper: see HtmlHelper::value.

    Using value insterad of tagValue seems to work great. Thanks to all for putting this together.
  • Posted 08/07/07 04:14:58 AM
    If we want it to work with the SecurityComponent without blackholing everything, another change is needed.

    It has to use FormHelper::input .. and actually this could be done by a little hack.

    $form->input('Model.field][');
    By appending ][ to the end the result will be
    [Model][field][] Something like we wanted all along.
  • Posted 06/11/07 12:18:12 PM
    I have 2 methods in my controller for binding the selected checkboxes

    function _explode($model, $field)
    { return((explode(",",$this->data[$model][$field])));
    }
    function _populateChkBoxList($model, $field){
    $tmp1=$this->_explode($model, $field);
    $tmpArr=array();
    foreach($tmp1 as $val){
    $tmpArr[$val]=$val;
    }
    return $tmpArr;
    }

    This is working fine..

    but how do i get a CSV from the add action ?

  • Posted 04/20/07 01:26:30 AM
    Kristoffer,

    Thanks for the heads up on the changes to "model()" and "field()". Regarding the other two errors, I solved those by putting the tag definitions right at the top of the function definition for checkboxMultiple.

    Like this:
    function checkboxMultiple($fieldName, $options, $selected = null, $inbetween = null, $htmlAttributes = null, $return = false) {
    # Tag template for an input type='hidden' tag.
    $hiddenmultiple = '';

    # Tag template for a input type='checkbox ' tag.
    $checkboxmultiple = '%s';

    $this->setFormTag($fieldName);

    ----------------------------------------->
    I came up with this quick solution in order to get the checkboxes to recognize existing selections. In my setup cars and sites have a habtm relationship between each other.

    if($this->data['Site'])
    {
    foreach($this->data['Site'] as $sv)
    {
    $selectedSites[$sv['id']] = $sv['name'];
    }
    }
    else
    {
    $selectedSites = '';
    }

    I put that in the "edit" method of my controller. Hope that helps.
    • Posted 08/06/07 10:52:24 PM
      Thank you Kristoffer & DF,

      I had to make all the changes you suggested to get it to work with 1.2

      The final code that works for 1.2 would be the following.


         function checkboxMultiple($fieldName, $options, $selected = null, $inbetween = null, $htmlAttributes = null, $return = false)
              {
                  # Tag template for a input type='checkbox ' tag.
                  $checkboxmultiple = '<input type="checkbox" name="data[%s][%s][]" %s/>%s';
                  # Tag template for an input type='hidden' tag.
                  $hiddenmultiple = '<input type="hidden" name="data[%s][%s][]" %s/>';

                  $this->setFormTag($fieldName);
                  if ($this->tagIsInvalid($this->model(), $this->field())) {
                      if (isset($htmlAttributes['class']) && trim($htmlAttributes['class']) != "") {
                          $htmlAttributes['class'] .= ' form_error';
                      } else {
                          $htmlAttributes['class'] = 'form_error';
                      }
                  }
                  if (!is_array($options)) {
                      return null;
                  }
                  if (!isset($selected)) {
                      $selected = $this->tagValue($fieldName);
                  }
                  foreach($options as $name => $title) {
                      $optionsHere = $htmlAttributes;
                      if (($selected !== null) && ($selected == $name)) {
                          $optionsHere['checked'] = 'checked';
                      } else if (is_array($selected) && array_key_exists($name, $selected)) {
                          $optionsHere['checked'] = 'checked';
                      }
                      $optionsHere['value'] = $name;
                      $checkbox[] = "<li>" . sprintf($checkboxmultiple, $this->model(), $this->field(), $this->_parseAttributes($optionsHere), $title) . "</li>\n";
                  }
                  return "\n" . sprintf($hiddenmultiple, $this->model(), $this->field(), null, $title) . "\n<ul class=\"checkboxMultiple\">\n" . $this->output(implode($checkbox), $return) . "</ul>\n";

              } /// checkboxMultiple()

      And this is how you use it...

      echo $myHtml->checkboxMultiple('MyModel/MyModel', $arrAllBoxes, $selectedBoxes, array('multiple' => 'multiple', 'class' => 'selectMultiple'));

      But the addition I had to make to the controller method was following.

                                  if($this->data['MyModel']['MyModel'])
                                  {
                                      foreach($this->data['MyModel']['MyModel'] as $selectedItem)
                                      {
                                          $selectedBoxes[$selectedItem] = $selectedItem;
                                      }
                                  }
                                  else
                                  {
                                      $selectedBoxes = '';
                                  }

  • Posted 04/18/07 05:37:36 PM
    At least changeing $this->model to $this->model() and $this->field to $this->field() seems to get rid of thoses errors. I don't know if the meaning is equavilent to the old way.

    But I get two other errors as well.
    Notice (8): Undefined index: checkboxmultiple [CORE/app/views/helpers/habtm.php, line 51]
    And:
    Notice (8): Undefined index: hiddenmultiple [CORE/app/views/helpers/habtm.php, line 55]
    They are not defined anywhere. I can't figure out why it works in 1.1 either. Well i solved it this way.

    I added

    $this->tags['checkboxmultiple'] = '%s';

    AND

    $this->tags['hiddenmultiple'] = '%s';

    in the beginning of the code directly above $this->setForm.
  • Posted 04/10/07 05:30:36 PM
    Thanks for the awesome helper and detailed steps to implement it! This is totally going to save me a ton of time. I'm attempting to use this with 1.2.0.4798alpha version and I'm seeing the following error messages.I tried searching the google groups and online in general and couldn't find anyone encountering similar issues.

    Notice (8): Undefined property: HabtmHelper::$model [CORE/app/views/helpers/habtm.php, line 20]
    Notice (8): Undefined property: HabtmHelper::$field [CORE/app/views/helpers/habtm.php, line 20]
    Any help is appreciated. Thanks again!
  • Posted 04/10/07 10:04:41 AM
    I've been playing around with the checkbox helper some more and getting some very odd results (using PHP 4.4.3) - basically if I attempt to save a data and it is invalid so you return to a view with the error message, the wrong checkboxes are ticked (although the $selected array is correct).

    Anyway I ended up rewriting part of the function (using while instead of foreach) - I was wondering if you had any ideas what the problem was - perhaps PHP4 vs 5?
    /**
    * Returns a list of checkboxes.
    *
    * @param string $fieldName Name attribute of the SELECT
    * @param array $options Array of the elements (as 'value'=>'Text' pairs)
    * @param array $selected Selected checkboxes
    * @param string $inbetween String that separates the checkboxes.
    * @param array $htmlAttributes Array of HTML options
    * @param boolean $return Whether this method should return a value
    * @return string List of checkboxes
    */
    function checkboxMultiple($fieldName, $options, $selected = null, $inbetween = null, $htmlAttributes = null, $return = false)
    {

    $this->setFormTag($fieldName);
    if ($this->tagIsInvalid($this->model, $this->field))
    {
    if (isset($htmlAttributes['class']) && trim($htmlAttributes['class']) != "")
    {
    $htmlAttributes['class'] .= ' form_error';
    }
    else
    {
    $htmlAttributes['class'] = 'form_error';
    }
    }

    if (!is_array($options))
    {
    return null;
    }

    if (!isset($selected))
    {
    $selected = $this->tagValue($fieldName);
    }

    while(list($key, $name) = each($options))
    {
    $optionsHere = $htmlAttributes;

    if(in_array($key, $selected))
    {
    $optionsHere['checked'] = 'checked';
    }

    $optionsHere['value'] = $key;
    $checkbox[] = "
  • " . sprintf($this->tags['checkboxmultiple'], $this->model, $this->field, $this->parseHtmlOptions($optionsHere), $name) . "
  • \n";
    }


    return "\n" . sprintf($this->tags['hiddenmultiple'], $this->model, $this->field, null, $name) . "\n
      \n" . $this->output(implode($checkbox), $return) . "
    \n";
    }

    }

    ?>
  • Posted 04/05/07 06:18:58 AM
    I've made a working example based on the Posts / Tags in the manual that anyone can download. It contains the views / models / controllers and has your helper already applied.

    Hope it comes in useful to somebody.

    http://www.flipflops.org/example/habtm_checkbox_example.zip
  • Posted 04/01/07 08:03:09 AM
    Thanks for the acknowledgment :) Great idea making it into a helper.

    Something like this (along with Neil's label modification) should make it's way into Cake I think.
  • Posted 03/28/07 06:17:54 AM
    I wanted labels attached to each check box for improved usability, so changed the definition of checkboxmultiple format in tags.ini.php to:

    checkboxmultiple=<input type="checkbox" name="data[%s][%s][]" %s/>
    i.e. removed the final %s and modified the helper function internals to:

    /**
     * Returns a list of checkboxes.
     *
     * @param string $fieldName Name attribute of the SELECT
     * @param array $options Array of the elements (as 'value'=>'Text' pairs)
     * @param array $selected Selected checkboxes
     * @param array $htmlAttributes Array of HTML options
     * @param array $containerAttributes Array of HTML attributes used for the containing tag
     * @param boolean $showEmpty If true, the empty checkbox option is shown
     * @param  boolean $return         Whether this method should return a value
     * @return string List of checkboxes
     */
        function checkboxMultiple($fieldName, $options, $selected = null, $htmlAttributes = null, $containerAttributes = null, $showEmpty = true, $return = false) {
            $this->Html->setFormTag($fieldName);
            if ($this->Html->tagIsInvalid($this->Html->model, $this->Html->field)) {
                if (isset($htmlAttributes['class']) && trim($htmlAttributes['class']) != "") {
                    $htmlAttributes['class'] .= ' form_error';
                } else {
                    $htmlAttributes['class'] = 'form_error';
                }
            }
            if (!is_array($options)) {
                return null;
            }
            if (!isset($selected)) {
                $selected = $this->Html->tagValue($fieldName);
            }
            if ($showEmpty == true) {
                $checkbox[] = sprintf($this->tags['hiddenmultiple'], $this->Html->model, $this->Html->field, $this->Html->parseHtmlOptions($htmlAttributes));
            }
            foreach($options as $name => $title) {
                $optionsHere = $htmlAttributes;
                if (!isset($htmlAttributes['id'])) {
                $optionsHere['id'] = $this->Html->model . Inflector::camelize($this->Html->field) . $name;
                }
                $optionsHere['value'] = $name;
                if (($selected !== null) && ($selected == $name)) {
                    $optionsHere['checked'] = 'checked';
                } else if (is_array($selected) && array_key_exists($name, $selected)) {
                    $optionsHere['checked'] = 'checked';
                }
                $checkbox[] = "<li>" . sprintf($this->tags['checkboxmultiple'], $this->Html->model, $this->Html->field, $this->Html->parseHtmlOptions($optionsHere), $title)
                                     . $this->Form->labelTag($fieldName . $name, $title) . "</li>\n";
            }
            return "\n<ul".$this->Html->parseHtmlOptions($containerAttributes).">\n" . $this->Html->output(implode($checkbox), $return) . "</ul>\n";
        }
    As you can see I've added the labelTag() method of the form helper to it, so we need to include the 'Form' helper in the array of helpers that this helper uses.

    I've also added the id attribute to the optionsHere array for each option, so that the label has something to attach itself to.

    I also wanted its use to be transparent with the Html helper's selectTag() method for multiple selects so modified the prototype by removing $inbetween and adding a $containerAttributes param that corresponds to the $optionAttributes param in selectTag(). It can be used to specify the class of the
      . I also added the $showEmpty param just like in selectTag().

      To invoke it you might use something like this:

      $habtm->checkboxMultiple('YourModel/YourModel', $options, $selected, array('class' => 'checkbox'), array('class' => 'checkboxMultiple'), true, true);

      Hope its useful
  • Posted 03/20/07 10:05:10 PM
    Sorry about that Chris, I forgot the tag templates from the trac page. Doh!
  • Posted 03/20/07 05:50:32 PM
    I've had a problem with using checkboxes for the longest time and this seems to be a great solution, thanks for putting it together. A couple issues came out of trying to use this though.. first, I don't have any tag definitions for 'hiddenmultiple' or 'checkboxmultiple'. I removed the 'multiple's from those definitions, and put in the $title var and got it to sort of work, but then comes the issue of naming the field. i.e., I have a 'Language' with a HABTM to 'Profile', and normally, I'd name the field 'Language/Language', but that doesn't seem to work in this case. It might work fine once we get those tag definitions though. Thanks again...

    -ascendvisual
  • Posted 03/20/07 06:13:18 AM
    If you alter the CSS for the UL slightly you can accommodate many options on the form and not have them break the layout too much:

    ul.checkboxMultiple {
    margin:0;
    padding:0;
    height: 8em;
    overflow: auto;
    list-style-type:none;
    }

    This will limit the list to 8(ish) visible items and provide display scrollbar to reach the others.
  • Comments are closed for articles over a year old