Pull to refresh

Yii расширяем CHtml для работы с текстовыми полями

Reading time 6 min
Views 13K
Всем привет. Сейчас занимаюсь написанием очередного проекта на Yii и хотел бы поделиться кое-какими наработками. В этой статье я хотел бы описать, каким образом можно расширять функциональность фреймворка с помощью наследования классов CHtml, CActiveForm. Тут нет ничего сложного и инновационного, я просто хотел бы поделиться этим. Моя задача состояла в том, чтобы создать 2 элемента:
  • Текст, который при нажатии превращается в input
  • Блок, имеющий определенную ширину, в который может не поместиться весь необходимый текст, но при наведении появляется подсказка


Вот пример результата работы следующего кода (код после хабраката):

image

<?php $form=$this->beginWidget('MActiveForm', array(<br/>
'id'=>'personal-form',<br/>
'enableAjaxValidation'=>false,<br/>
)); <br/>
 <br/>
?><br/>
<?php echo $form->errorSummary($model); ?><br/>
 <br/>
    <div class="row"><br/>
<?php echo $form->labelEx($model,'gender'); ?><br/>
<?php echo $form->labelField($model,'gender'); ?><br/>
<?php echo $form->error($model,'gender'); ?><br/>
</div><br/>
 <br/>
    <div class="row"><br/>
<?php echo $form->labelEx($model,'firstname'); ?><br/>
<?php echo $form->labelField($model,'firstname'); ?><br/>
<?php echo $form->error($model,'firstname'); ?><br/>
</div><br/>
 <br/>
    <div class="row"><br/>
<?php echo $form->labelEx($model,'secondname'); ?><br/>
<?php echo $form->labelField($model,'secondname'); ?><br/>
<?php echo $form->error($model,'secondname'); ?><br/>
</div><br/>
 <br/>
    <div class="row"><br/>
<?php echo $form->labelEx($model,'lastname'); ?><br/>
<?php echo $form->labelField($model,'lastname'); ?><br/>
<?php echo $form->error($model,'lastname'); ?><br/>
</div>           <br/>
<? $this->endWidget(); ?><br/>
 


Когда я писал первую форму, я сообразил, что в yii использую стандартный виджет CActiveForm и было бы неплохо продолжать его использовать. В конце концов теперь я могу выводить поля формы таким образом (только виджет MActiveForm):

<?php echo $form->labelField($model,'secondname'); ?>

На деле CActiveForm является лишь зеркалом для методов типа activeTextField класса CHtml, поэтому пришлось расширить класс CHtml
и добавить в него функцию activeLabelField (назовем наш пользовательский элемент управления labelField)

<?php<br/>
 <br/>
class MHtml extends CHtml<br/>
{<br/>
    static $msPublished = false; // зерегистрированы ли необходимые файлы css и js<br/>
 <br/>
    protected static function registerMHtmlAsset()<br/>
    {<br/>
        if(!MHtml::$msPublished)<br/>
        {          <br/>
            $path = Yii::app()->getAssetManager()->publish(Yii::getPathOfAlias('application.components.assets.mhtml'), false, -1, true); // последний параметр рекомендуется поставить в false, потому что из-за этого наши файлы всё время заново копируются в папку asset (это удобно для отладки)<br/>
            Yii::app()->getClientScript()->registerScriptFile($path.'/mhtml.js', CClientScript::POS_END);<br/>
            Yii::app()->getClientScript()->registerCssFile($path.'/mhtml.css');<br/>
            MHtml::$msPublished = true;<br/>
        }<br/>
    }<br/>
    public static function addClass($class, $htmlOptions = array())<br/>
    {<br/>
        if(isset($htmlOptions["class"]))<br/>
            $htmlOptions["class"] .= " ".$class;<br/>
        else $htmlOptions["class"] = $class;<br/>
 <br/>
        return $htmlOptions;<br/>
    }<br/>
    public static function labelField($name, $value = '', $htmlOptions = array())<br/>
    {       <br/>
        MHtml::registerMHtmlAsset();<br/>
        return MHtml::textField($name, $value, MHtml::addClass("labelInput", $htmlOptions));<br/>
    }<br/>
 <br/>
    public static function activeLabelField($model,$attribute,$htmlOptions=array())<br/>
{<br/>
    MHtml::registerMHtmlAsset();<br/>
self::resolveNameID($model,$attribute,$htmlOptions);<br/>
self::clientChange('change',$htmlOptions);<br/>
return self::activeInputField('text',$model,$attribute, MHtml::addClass("labelInput", $htmlOptions));<br/>
}<br/>
 <br/>
    public static function textHint($text, $htmlOptions = array())<br/>
    {<br/>
        MHtml::registerMHtmlAsset();<br/>
 <br/>
        return MHtml::tag('div', MHtml::addClass("textHint_mh", $htmlOptions), $text);<br/>
    }<br/>
}<br/>
?>



Немного поясню. Для создания текста со всплывающей подсказкой мы просто создаем div с классом textHint_mh.

А для создания текста, который при клике превращается в текстовое поле, мы создаем input поле с классом labelInput, который после загрузки javascript кода будет спрятан и вместо него будет показан div с классом textHint_mh.

Вот такая вот запутанная ерунда. Теперь нам необходимо расширить класс CActiveForm:

<?php<br/>
 <br/>
class MActiveForm extends CActiveForm<br/>
{<br/>
    public function labelField($model,$attribute,$htmlOptions=array())<br/>
{<br/>
return MHtml::activeLabelField($model,$attribute,$htmlOptions);<br/>
}<br/>
}



Пару строк. И далее в дело вступают js и css. Все работает, все просто. Надеюсь, кому-то пригодиться

Исходный код тут
Tags:
Hubs:
+5
Comments 12
Comments Comments 12

Articles