Skip to content

Commit

Permalink
Kirkhansen 9053 add radio button column (yiisoft#13126)
Browse files Browse the repository at this point in the history
* Added the RadioButtonColumn class and updated the changelog.

* - several enhancements:
- unit tests added
- changelog fixed

* Update CHANGELOG.md

* small markdown fixes

* fix travis: custom ID
  • Loading branch information
dynasource authored Dec 5, 2016
1 parent eb6ea11 commit 7dac3ed
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 0 deletions.
1 change: 1 addition & 0 deletions framework/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Yii Framework 2 Change Log
- Enh #6809: Added `yii\caching\Cache::$defaultDuration` property, allowing to set custom default cache duration (sdkiller)
- Enh #7333: Improved error message for `yii\di\Instance::ensure()` when a component does not exist (cebe)
- Enh #7420: Attributes for prompt generated with `renderSelectOptions` of `\yii\helpers\Html` helper (arogachev)
- Enh #9053: Added`yii\grid\RadioButtonColumn` (darwinisgod)
- Enh #9162: Added support of closures in `value` for attributes in `yii\widgets\DetailView` (arogachev)
- Enh #10896: Select only primary key when counting records in UniqueValidator (developeruz)
- Enh #11037: `yii.js` and `yii.validation.js` use `Regexp.test()` instead of `String.match()` (arogachev, nkovacs)
Expand Down
92 changes: 92 additions & 0 deletions framework/grid/RadioButtonColumn.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/

namespace yii\grid;

use Closure;
use yii\base\InvalidConfigException;
use yii\helpers\Html;

/**
* RadioButtonColumn displays a column of radio buttons in a grid view.
*
* To add a RadioButtonColumn to the [[GridView]], add it to the [[GridView::columns|columns]] configuration as follows:
*
* ```php
* 'columns' => [
* // ...
* [
* 'class' => 'yii\grid\RadioButtonColumn',
* 'radioOptions' => function ($model) {
* return [
* 'value' => $model['value'],
* 'checked' => $model['value'] == 2
* ];
* }
* ],
* ]
* ```
*
* @author Kirk Hansen <[email protected]>
* @since 2.0.11
*/
class RadioButtonColumn extends Column
{
/**
* @var string the name of the input radio button input fields.
*/
public $name = 'radioButtonSelection';
/**
* @var array|\Closure the HTML attributes for the radio buttons. This can either be an array of
* attributes or an anonymous function ([[Closure]]) returning such an array.
*
* The signature of the function should be as follows: `function ($model, $key, $index, $column)`
* where `$model`, `$key`, and `$index` refer to the model, key and index of the row currently being rendered
* and `$column` is a reference to the [[RadioButtonColumn]] object.
*
* A function may be used to assign different attributes to different rows based on the data in that row.
* Specifically if you want to set a different value for the radio button you can use this option
* in the following way (in this example using the `name` attribute of the model):
* ```php
* 'radioOptions' => function ($model, $key, $index, $column) {
* return ['value' => $model->attribute];
* }
* ```
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $radioOptions = [];


/**
* @inheritdoc
* @throws \yii\base\InvalidConfigException if [[name]] is not set.
*/
public function init()
{
parent::init();
if (empty($this->name)) {
throw new InvalidConfigException('The "name" property must be set.');
}
}

/**
* @inheritdoc
*/
protected function renderDataCellContent($model, $key, $index)
{
if ($this->radioOptions instanceof Closure) {
$options = call_user_func($this->radioOptions, $model, $key, $index, $this);
} else {
$options = $this->radioOptions;
if (!isset($options['value'])) {
$options['value'] = is_array($key) ? json_encode($key, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) : $key;
}
}
$checked = isset($options['checked']) ? $options['checked'] : false;
return Html::radio($this->name, $checked, $options);
}
}
105 changes: 105 additions & 0 deletions tests/framework/grid/RadiobuttonColumnTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/

namespace yiiunit\framework\grid;

use Yii;
use yii\data\ArrayDataProvider;
use yii\grid\GridView;
use yii\grid\RadioButtonColumn;
use yii\web\Request;
use yiiunit\TestCase;

/**
* Class RadiobuttonColumnTest
* @package yiiunit\framework\grid
* @since 2.0.11
*/
class RadiobuttonColumnTest extends TestCase
{
/**
* @expectedException \yii\base\InvalidConfigException
* @expectedExceptionMessage The "name" property must be set.
*/
public function testException()
{
new RadioButtonColumn([
'name' => null
]);
}

public function testOptionsByArray()
{
$column = new RadioButtonColumn([
'radioOptions' => [
'value' => 42
]
]);
$this->assertEquals('<td><input type="radio" name="radioButtonSelection" value="42"></td>', $column->renderDataCell([], 1, 0));
}

public function testOptionsByCallback()
{
$model = [
'label' => 'label',
'value' => 123
];
$column = new RadioButtonColumn([
'radioOptions' => function ($model) {
return [
'value' => $model['value']
];
}
]);
$actual = $column->renderDataCell($model, 1, 0);
$this->assertEquals('<td><input type="radio" name="radioButtonSelection" value="' . $model['value'] . '"></td>', $actual);
}

public function testMultipleInGrid()
{
$this->mockApplication();
Yii::setAlias('@webroot', '@yiiunit/runtime');
Yii::setAlias('@web', 'http://localhost/');
Yii::$app->assetManager->bundles['yii\web\JqueryAsset'] = false;
Yii::$app->set('request', new Request(['url' => '/abc']));

$models = [
['label' => 'label1', 'value' => 1],
['label' => 'label2', 'value' => 2, 'checked' => true]
];
$grid = new GridView([
'dataProvider' => new ArrayDataProvider(['allModels' => $models]),
'options' => ['id' => 'radio-gridview'],
'columns' => [
[
'class' => RadioButtonColumn::className(),
'radioOptions' => function ($model) {
return [
'value' => $model['value'],
'checked' => $model['value'] == 2
];
}
]
]
]);
ob_start();
$grid->run();
$actual = ob_get_clean();
$this->assertEqualsWithoutLE(<<<HTML
<div id="radio-gridview"><div class="summary">Showing <b>1-2</b> of <b>2</b> items.</div>
<table class="table table-striped table-bordered"><thead>
<tr><th>&nbsp;</th></tr>
</thead>
<tbody>
<tr data-key="0"><td><input type="radio" name="radioButtonSelection" value="1"></td></tr>
<tr data-key="1"><td><input type="radio" name="radioButtonSelection" value="2" checked></td></tr>
</tbody></table>
</div>
HTML
, $actual);
}
}

0 comments on commit 7dac3ed

Please sign in to comment.