Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Render checkboxes and radios box groups #1155

Open
binhwpo opened this issue Dec 26, 2014 · 9 comments
Open

Render checkboxes and radios box groups #1155

binhwpo opened this issue Dec 26, 2014 · 9 comments

Comments

@binhwpo
Copy link

binhwpo commented Dec 26, 2014

Hello @nateabele and Team,

I'm working on a project using Lithium. Some pages require a list of checkboxes to be shown. We can just use HTML or individual Form->checkbox(...) and Form->radio(...) within foreach. But I find that's not very friendly for a template maker.

Therefore I made a working snippet of Form helper that can print out a list of checkboxes and radios (and anything) depending on what input type has been chosen.

I would like to contribute that to this project. I know it might not be perfect or following Lithium standards yet. But if consider we can optimize it then hopefully can be included as Lithium functions.

Here is the code:

<?php
namespace app\extensions\helper;

class Form extends \lithium\template\helper\Form {

    public function formlist($type, $name, $values = array(), $checks = array(), $options = array()) {

        $html = '';

        if ($prefix = @$options['prefix']) unset($options['prefix']);
        if ($suffix = @$options['suffix']) unset($options['suffix']);

        $id = str_replace(array('[]', ']', '['), array('', '', '-'), $name);

        foreach ($values as $value => $label) {
            $checked = is_array($checks) ? in_array($value, $checks) : ($value == $checks);
            $html .= "\n<label for=\"$id-$value\">";
            $html .= $prefix . $this->$type($name, array_merge($options, 
                array('id' => "$id-$value", 'value' => $value, 'checked' => $checked)));
            $html .= " $label</label>$suffix\n";
        }
        return $html;
    }

    public function checkboxes($name, $values = array(), $checks = array(), $options = array()) {
        $options = $options + array('hidden' => false);
        return $this->formlist('checkbox', $name, $values, $checks, $options);      
    }

    public function radios($name, $values = array(), $check = '', $options = array()) {
        return $this->formlist('radio', $name, $values, $check, $options);      
    }
}
?>
@DrRoach
Copy link
Contributor

DrRoach commented Dec 26, 2014

Modified the _fields method will do what you're looking for but using a lot less code. It's not perfect yet, you can only set options globally for the inputs but I'll fix that tomorrow if this is something that you're but maybe it's the sort of thing that you're looking for? Anyway, here's what I did if you want to use the code:

protected function _fields(array $fields, array $options = array()) {
     $result = array();

     foreach ($fields as $field => $label) {
         if (is_numeric($field)) {
             $field = $label;
             unset($label);
         }
         //Start of where I added
         if(is_array($label)) {
             foreach($label as $l => $opts) {
                 if(is_array($opts)) {
                     $result[] = $this->field($field, array('label' => $l) + $opts + $options);
                 } else {
                     $result[] = $this->field($field, array('label' => $opts) + $options);
                 }
             }
          } else {
             $result[] = $this->field($field, compact('label') + $options);
         }   
         //End of what I added
     }   
     return join("\n", $result);
 }

I added the if(is_array()) part which makes it so that you can add multiple inputs of any type using

$this->form->field(array('test' => array('Label' => array('id' => 'TestField', 'checked' => true), 'test')), array( 'type' => 'radio'))

This would create two radio buttons with the name test. The first field would have the id TestFIeld and be checked whereas the second field would use the default settings.

@binhwpo
Copy link
Author

binhwpo commented Dec 27, 2014

Hi @DrRoach,

Thanks for sharing your solution. I really appreciate your time to make some similar solution for my needs. I have been wondering how to use the field() and _fields() function too. It will be so great if we don't have to modify the _fields() function at all.

My function code seem to be a little longer then yours. However, it has a better benefit for a front-end developer. Most call to generate checkboxes and radios will be much easily understandable as example below:

$values = array("a" => "Option A", "b" => "Option B", "c" => "Option C");
echo $this->Form->checkboxes('somecheckboxes[]', $values, array("a", "c");); 
echo $this->Form->radios('someradios', $values, "b"); 

Results for checkboxes:
[x] Option A
[ ] Option B
[x] Option C

Results for radios:
( ) Option A
(o) Option B
( ) Option C

In additions they can include some prefix and suffix in an array of options.

Your solution on the other hand, will work great if the _fields function is not modified. But anyway, it's a good kickstart for me to start off investigating how to use the field function.

Many thanks.

@DrRoach
Copy link
Contributor

DrRoach commented Jan 6, 2015

Fair enough, I see your point, if you or other people want I will expand on what you have got to allow for extra features like adding ids and classes?

@binhwpo
Copy link
Author

binhwpo commented Jan 7, 2015

@DrRoach The main idea here is to have:

  1. Checkboxes/radios group name. A checkboxes group name normally end with [](accept many checks). eg: checklist[]
  2. I could see your code might do the same work. But the call for it is rather hard-to-understand on the template (mostly HTML) developer point of view. If it's officially added I still would rather make shorter interface functions checkboxes and radios as these are very oftently used.
  3. Prefix and suffix for these list items. Sometimes they prefer simple , (comma) <br />, <li>...</li>, hence having these will help because people can't interfere with the loop.
  4. ID and classes are optional and could be passed into $options input of field() already. So no change is required.

Many thanks.

@mariuswilms
Copy link
Member

Another idea would be to repurpose the 'list option as it was done for datalists and text inputs.
Please see cedc4d1

@DrRoach
Copy link
Contributor

DrRoach commented Jul 12, 2015

Using the list options means that you have to use $this->Form->field though doesn't it? While not really a issue this might seem strange to some developers when there is a radio option. I implemented a radios function which loops over the radio function in Form.php. I don't know if this is a potential solution?

public function radios($name, array $radios = array())
{
    $return = '';
    foreach($radios as $options) {
        $return .= $this->radio($name, $options);
    }

    return $return;
}

That's the code, shall I make a pull request?

@binhwpo
Copy link
Author

binhwpo commented Jul 13, 2015

@DavidPersson Thanks for looking at this again.
@DrRoach Thanks for providing a solution. I wonder how do we use this radios() function to print a list like mentioned above?

@DrRoach
Copy link
Contributor

DrRoach commented Jul 22, 2015

I don't know what the list functionality mentioned above does :/ So am not sure how to test that sorry.

@mariuswilms
Copy link
Member

My idea would be to not create additional radios/checkboxes methods, but make people utilize field() in combination with list. Than any multiple-XYZ logic could be contained within that method.

$this->form->field('colors', array('type' => 'checkbox', 'list' => array('b' => 'blue', 'g' => 'green));

At the same time field() should not be bloated too much, we might need to extract some functionality into protected methods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants