We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Radio buttons

Hi there, i was looking forward to 1.3.0, missing the Radio button. But now (i got 1.3.1) it seems it is not usable at all.. I hope someone will prove me wrong, but i just can't figure how to make a group of two dependent Radio buttons.

// will render only NO radio, because it is the last element of name "choice"?

use Phalcon\Forms\Element\Radio;

$yes = new Radio("choice", array("id" => "myYes", "value" => 1));
$yes->setLabel("YES!");

$no = new Radio("choice", array("id" => "myNo", "value" => 2));
$no->setLabel("NO!");

So, please, how can we render more than one radio button? And of course we need this Phalcon\Forms\Element\Radio, because we want to attach validatrions, filters..

And btw, maybe new category on this forum - "Forms" will come handy?

Thank You very much, J.



110

I have same problem .

edited Apr '14

Same here.

There is no example provided in the documentation, which makes it difficult to understand how to use this element. Hopefully the documentation will be updated with an example.

edited May '14

Running into the same problem myself. For anyone else that comes after me, this is what I've been doing. If you know of a better way though, please tell me.

In the form class:

    $test_radio = new Phalcon\Forms\Element\Radio('test');
    $test_radio->setLabel('my test radio');
    $test_radio->addValidators(array(
        //add any validators here
        new Phalcon\Validation\Validator\PresenceOf(array('message' => 'please fill in')),
        new Phalcon\Validation\Validator\InclusionIn(array(
            'message' => 'value not valid',
            'domain' => $assoc_array_of_possible_radio_values
        )),
    ));
    $this->add($test_radio);

Then in the view:

    foreach($assoc_array_of_possible_radio_values as $radio_value => $radio_name) {
        $attribs = array(
            'test' //<-- the same as the name set in the form class, must be 1st value in this array
            'value' => $radio_value,
        );
        if($actual_value_from_db_that_needs_to_be_preselected_on_form == $radio_value) $attribs['checked'] = 'checked';
        echo Phalcon\Tag::radioField($attribs);
        ?>
            <label for="visible_<?php echo $value; ?>" class="note">
                <strong><?php echo $radio_name); ?></strong>
            </label>
            <br />
        <?php
    }


7.3k
Accepted
answer

Ok, maybe it's quite obvious for someone, but for me it was not. I found a solution somewhere few days ago, can't find where, but this is quite it. I don't know if it's official and intended way, but here is what works for me:

$attr = array(
    'name' => 'groupName'
);

$radio1 = new \Phalcon\Forms\Element\Radio("radio1", $attr);
$radio2 = new \Phalcon\Forms\Element\Radio("radio2", $attr);

After you render those radios, it will be grouped together by name="groupName"!

Why the confusion?

$name in Radio($name) doesn't mean the name="" in HTML, but i guess it's only Phalcon internal name! I am maybe sorry for creating this post, but Radio documentation is completely missing (in 1.3.0 docs, which is available). So let's do some radios! :) Have a great day!

That worked great.

However, there's no way to attach PresenceOf validator to the group. Have you figured that out too?

Thanks!

Ok, maybe it's quite obvious for someone, but for me it was not. I found a solution somewhere few days ago, can't find where, but this is quite it. I don't know if it's official and intended way, but here is what works for me:

$attr = array(
   'name' => 'groupName'
);

$radio1 = new \Phalcon\Forms\Element\Radio("radio1", $attr);
$radio2 = new \Phalcon\Forms\Element\Radio("radio2", $attr);

After you render those radios, it will be grouped together by name="groupName"!

Why the confusion?

$name in Radio($name) doesn't mean the name="" in HTML, but i guess it's only Phalcon internal name! I am maybe sorry for creating this post, but Radio documentation is completely missing (in 1.3.0 docs, which is available). So let's do some radios! :) Have a great day!



51.3k

Alright, here's what I had to resort to in my Form class that's extending Phalcon's Form:

    public function isValid($data = null, $entity = null)
    {
        /**
         * A bit of a hack to get around the missing support of Validators on a group of RADIO items.
         *
         * Loop over defined elements of RADIO type and see whether their _attributes['name'] matches
         * a key in incoming data array.
         */
        foreach ($this->getElements() as $el) {
            if (!$el instanceof Radio) continue;
            // Find PresenceOf validator.
            if ($validators = $el->getValidators()) {
                if (empty($validators = array_filter($validators, function($validator) {
                    return ($validator instanceof PresenceOf);
                }))) {
                    // No PresenceOf validator exists on this Radio button.
                    continue;
                }
                if (isset($data[$k=$el->getAttribute('name')])) {
                    // Since each radio button of the group has own PresenceOf validator, we should augment
                    // input data array with the actual name of this radio button and its value.
                    // $el->setDefault() here does not do the trick.
                    $data[$el->getName()] = $data[$k];
                }
            }
        }

        if ($isValid = parent::isValid($data, $entity)) {
            ...
        }
   }


166

Hi! There is the solution I've end up with after struggling with radio buttons.

The main idea is, what are radio buttons? They are just "select" element having different visualization.

So, let's just:

  1. create an element as "select",
  2. add an attribute indicating that it should be shown as a radio button,
  3. create a function rendering such elements as a radio button
class InitialForm extends Form
{
    public function initialize($entity = null, $options = array())
    {
        # TEST RADIO BUTTON
        $gender = new Select('gender', array("M" => "Male", "F" => "Female"), array("is_radio" => true));
        $gender->setLabel('Gender');
        $this->add($gender);
    }
    public function showAsRadio($name)
    {
        $element = $this->get($name);

        # Check if there is any message

        $opts = $element->getOptions();
        $value = $element->getValue();

        foreach ($opts as $op_value => $op_lable) {
            echo '<input type="radio" name="', $name, '" value="', $op_value, '"';
            if ($op_value == $value) { echo ' checked '; }
            echo '>', $op_lable, '<br>';
        }
    }

}

Then in the view: if the attribute exist -> use the function

foreach ($form as $element) {
    echo '<div class="form-group">';
        echo '<label for="', $element->getName(), '">', $element->getLabel(), '</label>';
        if ($element->getAttribute('is_radio')) {
            $form->showAsRadio($element->getName());
        }
        else {
            echo $element;
        }
    echo '</div>';
}


51.3k

@Rustam

I really like your idea. Will see how that works in practice.

I use this code since they don't fix the issue.

if (!empty($entity) && $entity->getGender() == Employee::GENDER_MALE || $this->request->getPost('gender') == Employee::GENDER_MALE) {
            $this->add(new Radio('genderMale', ['value' => Employee::GENDER_MALE, 'name' => 'gender', 'checked' => 'checked', ]));
        } else {
            $this->add(new Radio('genderMale', ['value' => Employee::GENDER_MALE, 'name' => 'gender']));
        }

        if (!empty($entity) && $entity->getGender() == Employee::GENDER_FEMALE || $this->request->getPost('gender') == Employee::GENDER_FEMALE) {
            $this->add(new Radio('genderFemale', ['value' => Employee::GENDER_FEMALE, 'name' => 'gender','checked' => 'checked']));
        } else {
            $this->add(new Radio('genderFemale', ['value' => Employee::GENDER_FEMALE, 'name' => 'gender']));
        }

where $entity is the entity object, in my case, Employee class.

    $attr = ['value' => Employee::GENDER_MALE, 'name' => 'gender'];
        if (!empty($entity) && $entity->getGender() == Employee::GENDER_MALE || $this->request->getPost('gender') == Employee::GENDER_MALE) {
            $attr += ['checked' => 'checked'];
        }
        $el = new Radio('genderMale', $attr);
        $el->setLabel(t('Male'));
        $this->add($el);

        $attr = ['value' => Employee::GENDER_FEMALE, 'name' => 'gender'];
        if (!empty($entity) && $entity->getGender() == Employee::GENDER_FEMALE || $this->request->getPost('gender') == Employee::GENDER_FEMALE) {
            $attr += ['checked' => 'checked'];
        }
        $el = new Radio('genderFemale', $attr);
        $el->setLabel(t('Female'));
        $this->add($el);