在介紹 Yii 內建 UI 元件前,先說明如何自訂元件,這也有助於理解 CWidget 用法。自訂元件即重載 CWidget 的 init() 和 run() 方法:
class MyWidget extends CWidget {
public function init() {
// 此方法會被 CController::beginWidget() 呼叫
}
public function run() {
// 此方法會被 CController::endWidget() 呼叫
}
}
本例透過擴展 CInputWidget,定義一個數值範圍輸入 UI 元件 RangeInputField,允許使用者輸入兩個數字定義範圍。CInputWidget 支援使用 CModel 或直接使用變數,RangeInputField 保留此傳統。
$attributeFrom 和 $attributeTo:搭配 CModel 使用,配合 CHtml 的 activeXXX 方法自動產生標籤與輸入框。$nameFrom、$nameTo、$valueFrom、$valueTo:程式設計師可自行定義輸入框標籤。依 Yii 預設目錄結構,新建 protected/components/RangeInputField.php:
class RangeInputField extends CInputWidget {
public $attributeFrom;
public $attributeTo;
public $nameFrom;
public $nameTo;
public $valueFrom;
public $valueTo;
function run() {
if ($this->hasModel()) {
echo CHtml::activeTextField($this->model, $this->attributeFrom);
echo ' -> ';
echo CHtml::activeTextField($this->model, $this->attributeTo);
} else {
echo CHtml::textField($this->nameFrom, $this->valueFrom);
echo ' -> ';
echo CHtml::textField($this->nameTo, $this->valueTo);
}
}
protected function hasModel() {
return $this->model instanceof CModel
&& $this->attributeFrom !== null
&& $this->attributeTo !== null;
}
}
使用 FormModel(CModel)方式測試 RangeInputField。
在 protected/models 下建立 RangeForm.php:
class RangeForm extends CFormModel {
public $from;
public $to;
function rules() {
return array(
array('from,to', 'numerical', 'integerOnly' => true),
array('from', 'compare', 'compareAttribute' => 'to', 'operator' => '<=', 'skipOnError' => true),
);
}
}
修改 protected/controllers/SiteController.php 中的 actionIndex 方法:
public function actionIndex() {
$success = false;
$model = new RangeForm();
if (!empty($_POST['RangeForm'])) {
$model->attributes = $_POST['RangeForm'];
if ($model->validate()) $success = true;
}
$this->render('index', array(
'model' => $model,
'success' => $success,
));
}