Всем привет. Сейчас занимаюсь написанием очередного проекта на Yii и хотел бы поделиться кое-какими наработками. В этой статье я хотел бы описать, каким образом можно расширять функциональность фреймворка с помощью наследования классов CHtml, CActiveForm. Тут нет ничего сложного и инновационного, я просто хотел бы поделиться этим. Моя задача состояла в том, чтобы создать 2 элемента:
- Текст, который при нажатии превращается в input
- Блок, имеющий определенную ширину, в который может не поместиться весь необходимый текст, но при наведении появляется подсказка
Вот пример результата работы следующего кода (код после хабраката):
<?php $form=$this->beginWidget('MActiveForm', array(
'id'=>'personal-form',
'enableAjaxValidation'=>false,
));
?>
<?php echo $form->errorSummary($model); ?>
<div class="row">
<?php echo $form->labelEx($model,'gender'); ?>
<?php echo $form->labelField($model,'gender'); ?>
<?php echo $form->error($model,'gender'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'firstname'); ?>
<?php echo $form->labelField($model,'firstname'); ?>
<?php echo $form->error($model,'firstname'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'secondname'); ?>
<?php echo $form->labelField($model,'secondname'); ?>
<?php echo $form->error($model,'secondname'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'lastname'); ?>
<?php echo $form->labelField($model,'lastname'); ?>
<?php echo $form->error($model,'lastname'); ?>
</div>
<? $this->endWidget(); ?>
Когда я писал первую форму, я сообразил, что в yii использую стандартный виджет CActiveForm и было бы неплохо продолжать его использовать. В конце концов теперь я могу выводить поля формы таким образом (только виджет MActiveForm):
<?php echo $form->labelField($model,'secondname'); ?>
На деле CActiveForm является лишь зеркалом для методов типа activeTextField класса CHtml, поэтому пришлось расширить класс CHtml
и добавить в него функцию activeLabelField (назовем наш пользовательский элемент управления labelField)
<?php
class MHtml extends CHtml
{
static $msPublished = false; // зерегистрированы ли необходимые файлы css и js
protected static function registerMHtmlAsset()
{
if(!MHtml::$msPublished)
{
$path = Yii::app()->getAssetManager()->publish(Yii::getPathOfAlias('application.components.assets.mhtml'), false, -1, true); // последний параметр рекомендуется поставить в false, потому что из-за этого наши файлы всё время заново копируются в папку asset (это удобно для отладки)
Yii::app()->getClientScript()->registerScriptFile($path.'/mhtml.js', CClientScript::POS_END);
Yii::app()->getClientScript()->registerCssFile($path.'/mhtml.css');
MHtml::$msPublished = true;
}
}
public static function addClass($class, $htmlOptions = array())
{
if(isset($htmlOptions["class"]))
$htmlOptions["class"] .= " ".$class;
else $htmlOptions["class"] = $class;
return $htmlOptions;
}
public static function labelField($name, $value = '', $htmlOptions = array())
{
MHtml::registerMHtmlAsset();
return MHtml::textField($name, $value, MHtml::addClass("labelInput", $htmlOptions));
}
public static function activeLabelField($model,$attribute,$htmlOptions=array())
{
MHtml::registerMHtmlAsset();
self::resolveNameID($model,$attribute,$htmlOptions);
self::clientChange('change',$htmlOptions);
return self::activeInputField('text',$model,$attribute, MHtml::addClass("labelInput", $htmlOptions));
}
public static function textHint($text, $htmlOptions = array())
{
MHtml::registerMHtmlAsset();
return MHtml::tag('div', MHtml::addClass("textHint_mh", $htmlOptions), $text);
}
}
?>
Немного поясню. Для создания текста со всплывающей подсказкой мы просто создаем div с классом textHint_mh.
А для создания текста, который при клике превращается в текстовое поле, мы создаем input поле с классом labelInput, который после загрузки javascript кода будет спрятан и вместо него будет показан div с классом textHint_mh.
Вот такая вот запутанная ерунда. Теперь нам необходимо расширить класс CActiveForm:
<?php
class MActiveForm extends CActiveForm
{
public function labelField($model,$attribute,$htmlOptions=array())
{
return MHtml::activeLabelField($model,$attribute,$htmlOptions);
}
}
Пару строк. И далее в дело вступают js и css. Все работает, все просто. Надеюсь, кому-то пригодиться
Автор: shedy