Skip to content

Commit

Permalink
FormElement: Add RadioElement
Browse files Browse the repository at this point in the history
  • Loading branch information
sukhwinder33445 committed Sep 30, 2022
1 parent 239b215 commit ea466be
Show file tree
Hide file tree
Showing 2 changed files with 318 additions and 0 deletions.
168 changes: 168 additions & 0 deletions src/FormElement/RadioElement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
<?php

namespace ipl\Html\FormElement;

use ipl\Html\Attributes;
use ipl\Html\HtmlElement;
use ipl\Html\HtmlString;
use ipl\I18n\Translation;

class RadioElement extends InputElement
{
use Translation;

protected $type = 'radio';

protected $optionContent;

public function __construct($name, $attributes = null)
{
$this->setName($name);

$this->getAttributes()->registerAttributeCallback(
'options',
null,
[$this, 'setOptions']
);

// ZF1 compatibility:
$this->getAttributes()->registerAttributeCallback(
'multiOptions',
null,
[$this, 'setOptions']
);

$this->getAttributes()->registerAttributeCallback(
'disabled',
null,
[$this, 'disableOptions']
);

parent::__construct($name, $attributes);
}

/**
* Disable radio button that contains given value
*
* @param string $value
*
* @return $this
*/
public function disableOption(string $value): RadioElement
{
if ($option = $this->getOption($value)) {
$option->getAttributes()->add('disabled', true);
}

if ($this->getValue() == $value) {
$this->valid = false;
$this->addMessage("'$value' is not allowed here");
}

return $this;
}

/**
* Disable radio buttons that contain given values
*
* @param mixed $values array or string
*
* @return $this
*/
public function disableOptions($values): RadioElement
{
$values = (array) $values;
foreach ($values as $value) {
$this->disableOption($value);
}

return $this;
}

/**
* Get radio button with given value
*
* @param string $value
*
* @return InputElement|null
*/
public function getOption(string $value): ?InputElement
{
foreach ($this->optionContent as $radio) {
if ($radio->getValueAttribute() === $value) {
return $radio;
}
}

return null;
}

public function setValue($value)
{
parent::setValue($value);

foreach ($this->optionContent as $radio) {
$radio->getAttributes()->remove('checked');
if ($radio->getValueAttribute() === $value) {
$radio->addAttributes(['checked' => true]);
}
}
}

public function validate()
{
$value = $this->getValue();
if (
$value !== null
&& (! ($option = $this->getOption($value)) || $option->getAttributes()->has('disabled'))
) {
$this->valid = false;
$this->addMessage(sprintf($this->translate("'%s' is not allowed here"), $value));

return $this;
}

return parent::validate();
}

/**
* Prepare options
*
* @param array $options
*
* @return $this
*/
public function setOptions(array $options): RadioElement
{
foreach ($options as $value => $label) {
$input = new InputElement($this->getName(), [
'name' => $this->getName(),
'type' => $this->type,
'value' => $value
]);

$this->optionContent[$label] = $input;
}

return $this;
}

public function renderUnwrapped()
{
return $this->renderContent();
}

protected function assemble()
{
foreach ($this->optionContent as $label => $radioElm) {
$labelElm = new HtmlElement(
'label',
Attributes::create(['class' => 'radio-label']),
$radioElm,
HtmlString::create($label)
);

$this->addHtml($labelElm);
}
}
}
150 changes: 150 additions & 0 deletions tests/FormElement/RadioElementTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
<?php

namespace ipl\Tests\Html\FormElement;

use ipl\Html\FormElement\RadioElement;
use ipl\I18n\NoopTranslator;
use ipl\I18n\StaticTranslator;
use ipl\Tests\Html\TestCase;

class RadioElementTest extends TestCase
{
public function testCreateRadioElementsCorrectly()
{
$radio = new RadioElement('test', [
'label' => 'Test',
'multiOptions' => [
'foo' => 'Foo',
'bar' => 'Bar',
'yes' => 'Yes'
]
]);

$this->assertHtml(
'<label class="radio-label"><input value="foo" name="test" type="radio">Foo</label>'
. '<label class="radio-label"><input value="bar" name="test" type="radio">Bar</label>'
. '<label class="radio-label"><input value="yes" name="test" type="radio">Yes</label>',
$radio
);
}

public function testCheckCorrectRadio()
{
$radio = new RadioElement('test', [
'label' => 'Test',
'multiOptions' => [
'foo' => 'Foo',
'bar' => 'Bar',
'yes' => 'Yes'
],
'value' => 'bar'
]);

$this->assertHtml(
'<label class="radio-label"><input value="foo" name="test" type="radio">Foo</label>'
. '<label class="radio-label"><input value="bar" name="test" type="radio" checked>Bar</label>'
. '<label class="radio-label"><input value="yes" name="test" type="radio">Yes</label>',
$radio
);

$radio->setValue('yes');

$this->assertHtml(
'<label class="radio-label"><input value="foo" name="test" type="radio">Foo</label>'
. '<label class="radio-label"><input value="bar" name="test" type="radio">Bar</label>'
. '<label class="radio-label"><input value="yes" name="test" type="radio" checked>Yes</label>',
$radio
);

$radio->setValue('no');

$this->assertHtml(
'<label class="radio-label"><input value="foo" name="test" type="radio">Foo</label>'
. '<label class="radio-label"><input value="bar" name="test" type="radio">Bar</label>'
. '<label class="radio-label"><input value="yes" name="test" type="radio">Yes</label>',
$radio
);
}

public function testDisableRadio()
{
$radio = new RadioElement('test', [
'label' => 'Test',
'multiOptions' => [
'foo' => 'Foo',
'bar' => 'Bar',
'yes' => 'Yes',
'no' => 'No'
],
'value' => 'bar',
'disabled' => 'yes'
]);

$this->assertHtml(
'<label class="radio-label"><input value="foo" name="test" type="radio">Foo</label>'
. '<label class="radio-label"><input value="bar" name="test" type="radio" checked>Bar</label>'
. '<label class="radio-label"><input value="yes" name="test" type="radio" disabled>Yes</label>'
. '<label class="radio-label"><input value="no" name="test" type="radio">No</label>',
$radio
);

$radio->disableOptions(['yes', 'no', 'foo']);

$this->assertHtml(
'<label class="radio-label"><input value="foo" name="test" type="radio" disabled>Foo</label>'
. '<label class="radio-label"><input value="bar" name="test" type="radio" checked>Bar</label>'
. '<label class="radio-label"><input value="yes" name="test" type="radio" disabled>Yes</label>'
. '<label class="radio-label"><input value="no" name="test" type="radio" disabled>No</label>',
$radio
);
}

public function testRadioNotValidIfCheckedValueIsInvalid()
{
StaticTranslator::$instance = new NoopTranslator();
$radio = new RadioElement('test', [
'label' => 'Test',
'multiOptions' => [
'foo' => 'Foo',
'bar' => 'Bar',
'yes' => 'Yes'
],
'value' => 'bar',
'disabled' => 'yes'
]);

$this->assertTrue($radio->isValid());

$radio->setValue('no');
$this->assertFalse($radio->isValid());

$radio->setValue('tom');
$this->assertFalse($radio->isValid());
}

public function testRadioNotValidIfCheckedValueIsDisabled()
{
StaticTranslator::$instance = new NoopTranslator();
$radio = new RadioElement('test', [
'label' => 'Test',
'multiOptions' => [
'foo' => 'Foo',
'bar' => 'Bar',
'yes' => 'Yes'
],
'value' => 'bar',
'disabled' => 'yes'
]);

$this->assertTrue($radio->isValid());

$radio->setValue('yes');
$this->assertFalse($radio->isValid());

$radio->setValue('bar');
$this->assertTrue($radio->isValid());

$radio->disableOptions(['bar', 'yes', 'foo']);
$this->assertFalse($radio->isValid());
}
}

0 comments on commit ea466be

Please sign in to comment.