Attaching and triggering EVENT to ActiveField

Hi,

is there any way to create and trigger any of following events in \yii\bootstrap\ActiveForm or ActiveField ?


ActiveForm::EVENT_FIELD_BEFORE_CREATE

ActiveForm::EVENT_FIELD_BEFORE_RENDER

ActiveField::EVENT_BEFORE_RENDER



The goal is to adjust dynamically HTML options before rendering ANY field.

Thank you for any word of wisdom :slight_smile:

Lubos

Since these events are not triggered in the ActiveForm/ActiveField classes the only solution I see would be extending these classes.

If your goal is only to adjust HTML options you probably don’t need to use Events at all. You can just extend the classes and modify whatever you need.

Just for the inspiration I’m posting an extended ActiveField class I used in some of my projects:


<?php


namespace frontend\widgets;


use yii\helpers\ArrayHelper;


/**

 * Customized version of [[\yii\bootstrap\ActiveField]].

 *

 * This class adds configurable options for Radio Lists and Checkbox Lists.

 */

class ActiveField extends \yii\bootstrap\ActiveField

{

    /**

     * @var array the default options for the Radio Lists.

     */

    public $radioListOptions = [];


    /**

     * @var array the default options for the Checkbox Lists.

     */

    public $checkboxListOptions = [];


    /**

     * @inheritdoc

     */

    public function radioList($items, $options = [])

    {

        $options = array_merge($this->radioListOptions, $options);

        parent::radioList($items, $options);

        return $this;

    }


    /**

     * @inheritdoc

     */

    public function checkboxList($items, $options = [])

    {

        $options = array_merge($this->checkboxListOptions, $options);

        parent::checkboxList($items, $options);

        return $this;

    }

}



And here is some sample usage with customized rendering of items:


$form = ActiveForm::begin([

    'fieldClass' => 'frontend\widgets\ActiveField',

    'fieldConfig' => [

        'radioListOptions' => [

            'class' => 'sample-class',

            'tag' => false,

            'item' => function ($index, $label, $name, $checked, $value) {

                return Html::radio($name, $checked, ['value' => $value]) . ' ' . $label;

            },

        ],

    ],

]);

Just for the clarification the options above are applied to any field in the form. For example:


<?= $form->field($model, 'sample_field')->radioList([0 => 'Zero', 1 => 'One']) ?>

Thank you for your answer.

Yes, I know about extending ActiveForm & ActiveField, that was my “heavy solution” before, which stored huge data into session. Therefore I’ve been looking for more flexible solution … like attaching global event or injecting event into object configuration. I am just not quite familiar with Yii2 events.

OK, I will probably go with this solution, even though I hoped to avoid extending.

(just for info - the reason to avoid extending is to keep loaded files at minimum, because profiling shows Yii2 -includes cca 80 files- is actually slower against Yii1 -includes cca 30-40 files- … though the difference of including 2 more files is actually negligible …)

I see. Perhaps there is some better approach I’m not aware of, but I don’t see a way how to attach events if they are not triggered inside the class.

A good example of how events are implemented in Yii 2 could be in the yii\db\BaseActiveRecord class.