diff --git a/CHANGELOG.md b/CHANGELOG.md index f1b1203..45747d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ Yii Framework 2 bootstrap5 extension Change Log 2.0.3 under development ----------------------- -- no changes in this release. +- Enh #18: Add rangeInput(), colorInput() and switch mode to checkbox() in class ActiveField (WinterSilence) 2.0.2 October 21, 2021 diff --git a/docs/guide/usage-widgets.md b/docs/guide/usage-widgets.md index 026554d..a199147 100644 --- a/docs/guide/usage-widgets.md +++ b/docs/guide/usage-widgets.md @@ -26,6 +26,11 @@ framework features. All widgets belong to `\yii\bootstrap5` namespace: - [[yii\bootstrap5\Toast|Toast]] - [[yii\bootstrap5\ToggleButtonGroup|ToggleButtonGroup]] +## ActiveField: additional fields + +- [Range](https://getbootstrap.com/docs/5.1/forms/range/): `$form->rangeInput(['min' => 0, 'max' => 100, 'step' => 1])` +- [Color picker](https://getbootstrap.com/docs/5.1/forms/form-control/#color): `$form->colorInput()` +- [Switch](https://getbootstrap.com/docs/5.1/forms/checks-radios/#switches): `$form->checkbox(['switch' => true])` ## Customizing widget CSS classes diff --git a/src/ActiveField.php b/src/ActiveField.php index 9dd1811..22e5036 100644 --- a/src/ActiveField.php +++ b/src/ActiveField.php @@ -166,6 +166,10 @@ class ActiveField extends \yii\widgets\ActiveField * @var string the template for checkboxes in default layout */ public $checkTemplate = "
\n{input}\n{label}\n{error}\n{hint}\n
"; + /** + * @var string the template forswitches (custom checkboxes) in default layout + */ + public $switchTemplate = "
\n{input}\n{label}\n{error}\n{hint}\n
"; /** * @var string the template for radios in default layout * @since 2.0.5 @@ -175,6 +179,10 @@ class ActiveField extends \yii\widgets\ActiveField * @var string the template for checkboxes and radios in horizontal layout */ public $checkHorizontalTemplate = "{beginWrapper}\n
\n{input}\n{label}\n{error}\n{hint}\n
\n{endWrapper}"; + /** + * @var string the template for switches (custom checkboxes) in horizontal layout + */ + public $switchHorizontalTemplate = "{beginWrapper}\n
\n{input}\n{label}\n{error}\n{hint}\n
\n{endWrapper}"; /** * @var string the template for checkboxes and radios in horizontal layout * @since 2.0.5 @@ -184,6 +192,10 @@ class ActiveField extends \yii\widgets\ActiveField * @var string the `enclosed by label` template for checkboxes and radios in default layout */ public $checkEnclosedTemplate = "
\n{beginLabel}\n{input}\n{labelTitle}\n{endLabel}\n{error}\n{hint}\n
"; + /** + * @var string tthe `enclosed by label` template for switches(custom checkboxes) in default layout + */ + public $switchEnclosedTemplate = "
\n{beginLabel}\n{input}\n{labelTitle}\n{endLabel}\n{error}\n{hint}\n
"; /** * @var bool whether to render the error. Default is `true` except for layout `inline`. */ @@ -245,6 +257,8 @@ class ActiveField extends \yii\widgets\ActiveField /** * {@inheritdoc} + * Enable option `switch` to render as toggle switch. + * @see https://getbootstrap.com/docs/5.1/forms/checks-radios/#switches */ public function checkbox($options = [], $enclosedByLabel = false) { @@ -255,21 +269,31 @@ class ActiveField extends \yii\widgets\ActiveField Html::removeCssClass($options, 'form-control'); $this->labelOptions = ArrayHelper::merge($this->labelOptions, $labelOptions); $this->wrapperOptions = ArrayHelper::merge($this->wrapperOptions, $wrapperOptions); + $switch = isset($options['switch']) && $options['switch']; + if ($switch) { + $this->addRoleAttributes($options, 'switch'); + } if (!isset($options['template'])) { - $this->template = ($enclosedByLabel) ? $this->checkEnclosedTemplate : $this->checkTemplate; + if ($switch) { + $this->template = $enclosedByLabel ? $this->switchEnclosedTemplate : $this->switchTemplate; + } else { + $this->template = $enclosedByLabel ? $this->checkEnclosedTemplate : $this->checkTemplate; + } } else { $this->template = $options['template']; } if ($this->form->layout === ActiveForm::LAYOUT_HORIZONTAL) { if (!isset($options['template'])) { - $this->template = $this->checkHorizontalTemplate; + $this->template = ($switch) + ? $this->switchHorizontalTemplate + : $this->checkHorizontalTemplate; } Html::removeCssClass($this->labelOptions, $this->horizontalCssClasses['label']); Html::addCssClass($this->wrapperOptions, $this->horizontalCssClasses['offset']); } Html::removeCssClass($this->labelOptions, 'form-label'); - unset($options['template']); + unset($options['template'], $options['switch']); if ($enclosedByLabel) { if (isset($options['label'])) { @@ -482,6 +506,41 @@ class ActiveField extends \yii\widgets\ActiveField return parent::fileInput($options); } + /** + * Renders a range (custom input). + * + * @param array $options the tag options in terms of name-value pairs: + * + * - 'min': min. value + * - 'max': max. value + * - 'step': range step, by default, 1 + * + * @return $this + * @see https://getbootstrap.com/docs/5.1/forms/range/ + */ + public function rangeInput(array $options = []) + { + Html::removeCssClass($options, 'form-control'); + Html::addCssClass($options, ['widget' => 'form-range']); + + return $this->input('range', $options); + } + + /** + * Renders a color picker (custom input). + * + * @param array $options the tag options in terms of name-value pairs + * @return $this + * @see https://getbootstrap.com/docs/5.1/forms/form-control/#color + */ + public function colorInput(array $options = []) + { + Html::removeCssClass($options, 'form-control'); + Html::addCssClass($options, ['widget' => 'form-control form-control-color']); + + return $this->input('color', $options); + } + /** * @param array $instanceConfig the configuration passed to this instance's constructor * @return array the layout specific default configuration for this instance diff --git a/tests/ActiveFieldTest.php b/tests/ActiveFieldTest.php index 71ed873..6d82135 100644 --- a/tests/ActiveFieldTest.php +++ b/tests/ActiveFieldTest.php @@ -28,7 +28,6 @@ class ActiveFieldTest extends TestCase public function testFileInput() { - Html::$counter = 0; $html = $this->activeField->fileInput()->render(); $expectedHtml = <<Attribute Name +
+ +HTML; + + $this->assertEqualsWithoutLE($expectedHtml, $html); + } + + public function testRangeInput() + { + $html = $this->activeField->rangeInput()->render(); + + $expectedHtml = << + + + +
+ +HTML; + + $this->assertEqualsWithoutLE($expectedHtml, $html); + } + + public function testColorInput() + { + $html = $this->activeField->colorInput()->render(); + + $expectedHtml = << + + +
HTML; @@ -45,7 +76,6 @@ HTML; public function testRadioList() { - Html::$counter = 0; $html = $this->activeField->radioList([1 => 'name1', 2 => 'name2'])->render(); $expectedHtml = <<helperModel->addError($this->attributeName, 'Test print error message'); $html = $this->activeField->radio()->render(); @@ -91,7 +120,6 @@ HTML; public function testRadioListError() { - Html::$counter = 0; $this->helperModel->addError($this->attributeName, 'Test print error message'); $html = $this->activeField->radioList([1 => 'name1', 2 => 'name2'])->render(); @@ -117,7 +145,6 @@ HTML; public function testCheckboxList() { - Html::$counter = 0; $html = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render(); $expectedHtml = << + +HTML; + $this->assertEqualsWithoutLE($expectedHtml, $html); + } + + /** + * @test checkbox + */ + public function testCheckboxSwitch() + { + $html = $this->activeField->checkbox(['switch' => true])->render(); + + $expectedHtml = << +
+ + +
+ +
HTML; $this->assertEqualsWithoutLE($expectedHtml, $html); @@ -142,7 +189,6 @@ HTML; public function testCheckboxError() { - Html::$counter = 0; $this->helperModel->addError($this->attributeName, 'Test print error message'); $html = $this->activeField->checkbox()->render(); @@ -161,7 +207,6 @@ HTML; public function testCheckboxListError() { - Html::$counter = 0; $this->helperModel->addError($this->attributeName, 'Test print error message'); $html = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render(); @@ -187,7 +232,6 @@ HTML; public function testRadioListInline() { - Html::$counter = 0; $this->activeField->inline = true; $html = $this->activeField->radioList([1 => 'name1', 2 => 'name2'])->render(); @@ -213,7 +257,6 @@ HTML; public function testCheckboxListInline() { - Html::$counter = 0; $this->activeField->inline = true; $html = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render(); @@ -238,12 +281,10 @@ HTML; } /** - * * @see https://github.com/yiisoft/yii2-bootstrap/issues/81 */ public function testRadioListItemOptions() { - Html::$counter = 0; $content = $this->activeField->radioList([1 => 'name1', 2 => 'name2'], [ 'itemOptions' => [ 'data-attribute' => 'test' @@ -259,7 +300,6 @@ HTML; */ public function testCheckboxListItemOptions() { - Html::$counter = 0; $content = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'], [ 'itemOptions' => [ 'data-attribute' => 'test' @@ -274,9 +314,10 @@ HTML; // dirty way to have Request object not throwing exception when running testHomeLinkNull() $_SERVER['SCRIPT_FILENAME'] = "index.php"; $_SERVER['SCRIPT_NAME'] = "index.php"; - parent::setUp(); + Html::$counter = 0; + $this->helperModel = new DynamicModel(['attributeName']); ob_start(); $this->helperForm = ActiveForm::begin(['action' => '/something']);