在介紹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 也保留了這一傳統。
RangeInputField定義了 三組屬性。
$attributeFrom 和 $attributeTo 用於CModel,配合CHtml的 activeXXX 方法,activeXXX可以自動生成文本框 的標簽和文本框。
屬性$nameFrom,$nameTo,$valueFrom,$valueTo 程序員可以自行定義文本框的標簽。
按照Yii 應用的缺省目錄結構,新創建的RangeInputField 放在 protected/components 目錄下,因此創建 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);
}
}
/**
* @return boolean whether this widget
* is associated with a data model.
*/
protected function hasModel()
{
return $this->model instanceof CModel
&& $this->attributeFrom!==null
&& $this->attributeTo!==null;
}
}
這樣就自定義了一個新的UI組件RangeInputField ,只重載了run 方法, init 使用其父類中的方法。
下面 就可以來測試這個新創建的自定義UI組件RangeInputField, 我們使用FormModel (使用CModel)的方法來使用這個UI組件。
在protected/models下創建RangeFrom.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),
);
}
}
然後修改缺省Controller的缺省方法, protected/controllers/siteController.php 中 actionIndex 方法。
public function actionIndex()
{
$success=false;
$model=new RangeForm();
if(!emptyempty($_POST['RangeForm']))
{
$model->attributes=$_POST['RangeForm'];
if($model->validate()) $success=true;
}
$this->render('index', array(
'model' => $model,
'success' => $success,
));
}