创建一个自定义输入小部件

Yii有一套非常好的表单小部件,但和其它框架一样,Yii并不能涵盖所有。在本小节中,我们将会学习如何创建自己的输入小部件。这里我们将创建一个范围输入小部件。

准备

按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的应用。

如何做…

  1. 创建一个小组件文件@app/components/RangeInputWidget.php
  1. <?php
  2. namespace app\components;
  3. use yii\base\Exception;
  4. use yii\base\Model;
  5. use yii\base\Widget;
  6. use yii\helpers\Html;
  7. class RangeInputWidget extends Widget
  8. {
  9. public $model;
  10. public $attributeFrom;
  11. public $attributeTo;
  12. public $htmlOptions = [];
  13. protected function hasModel()
  14. {
  15. return $this->model instanceof Model&&
  16. $this->attributeFrom !== null&& $this->attributeTo !== null;
  17. }
  18. public function run()
  19. {
  20. if (!$this->hasModel()) {
  21. throw new Exception('Model must be set');
  22. }
  23. return Html::activeTextInput($this->model, $this->attributeFrom, $this->htmlOptions)
  24. .' &rarr; '
  25. .Html::activeTextInput($this->model, $this->attributeTo, $this->htmlOptions);
  26. }
  27. }
  1. 创建一个控制器文件@app/controllers/RangeController.php
  1. <?php
  2. namespace app\controllers;
  3. use Yii;
  4. use yii\web\Controller;
  5. use app\models\RangeForm;
  6. class RangeController extends Controller
  7. {
  8. public function actionIndex()
  9. {
  10. $model = new RangeForm();
  11. if ($model->load(Yii::$app->request->post()) &&
  12. $model->validate()) {
  13. Yii::$app->session->setFlash('rangeFormSubmitted',
  14. 'The form was successfully processed!'
  15. );
  16. }
  17. return $this->render('index', array(
  18. 'model' => $model,
  19. ));
  20. }
  21. }
  1. 创建一个表单文件@app/models/RangeForm.php
  1. <?php
  2. namespace app\models;
  3. use yii\base\Model;
  4. class RangeForm extends Model
  5. {
  6. public $from;
  7. public $to;
  8. public function rules()
  9. {
  10. return [
  11. [['from', 'to'], 'number', 'integerOnly' => true],
  12. ['from', 'compare', 'compareAttribute' => 'to',
  13. 'operator' => '<='],
  14. ];
  15. }
  16. }
  1. 创建一个视图文件@app/views/range/index.php
  1. <?php
  2. use yii\helpers\Html;
  3. use yii\bootstrap\ActiveForm;
  4. use app\components\RangeInputWidget;
  5. ?>
  6. <h1>Range form</h1>
  7. <?php if (Yii::$app->session->hasFlash('rangeFormSubmitted')):
  8. ?>
  9. <div class="alert alert-success">
  10. <?= Yii::$app->session->getFlash('rangeFormSubmitted');
  11. ?>
  12. </div>
  13. <?php endif?>
  14. <?= Html::errorSummary($model, ['class'=>'alert alert-danger'])?>
  15. <?php $form = ActiveForm::begin([
  16. 'options' => [
  17. 'class' => 'form-inline'
  18. ]
  19. ]); ?>
  20. <div class="form-group">
  21. <?= RangeInputWidget::widget([
  22. 'model' => $model,
  23. 'attributeFrom' => 'from',
  24. 'attributeTo' => 'to',
  25. 'htmlOptions' => [
  26. 'class' =>'form-control'
  27. ]
  28. ]) ?>
  29. </div>
  30. <?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?>
  31. <?php ActiveForm::end(); ?>
  1. 打开网页index.php?r=range运行range控制器:

创建一个自定义输入小部件 - 图1

  1. 第一个文本输入字段输入200,第二个输入300:

创建一个自定义输入小部件 - 图2

  1. 如果第一个值比第二个值大,小部件会输出一个错误。尝试输入正确的值,分别输入100和200:

创建一个自定义输入小部件 - 图3

工作原理…

范围输入小部件需要如下四个参数:

  • model:如果没有设置,会抛出一个异常
  • attributeFrom:用于设置范围的最小值
  • attributeTo:用于设置范围的最大值
  • htmlOptions:会被传递给每一个输入

这个小部件用在表单验证,被用于检查第一个值是否小于等于第二个值。

更多…

Yii2框架有一个官方Twitter Bootstrap扩展,它提供了一系列Twitter Bootstrap小部件的封装。在你使用自己的小部件时,检查有否有Bootstrap可用http://www.yiiframework.com/doc-2.0/extbootstrap-index.html

参考

欲了解更多关于小部件的信息,可以使用如下资源: