yiisoft / yii-widgets

Collection of useful widgets for Yii Framework
https://www.yiiframework.com/
BSD 3-Clause "New" or "Revised" License
17 stars 7 forks source link

Enhance ActiveField::widget() flexibility #3

Closed dynasource closed 4 years ago

dynasource commented 8 years ago

What steps will reproduce the problem?

Before using this function, you have to separate the class from its options. In 99% of the time one should not have to do this.

What is the expected result?

I would expect similar functionality like with Yii::createObject. Passing around arrays with classes should be supported

What do you get instead?

You have to separate it everytime yourself. The current implementation is not flexible and inconsistent with other area's where configuration arrays with included class parameters are supported.

Instead of:

    public function widget($class, $config = [])
    {
        /* @var $class \yii\base\Widget */
        $config['model'] = $this->model;
        $config['attribute'] = $this->attribute;
        $config['view'] = $this->form->getView();
        $this->parts['{input}'] = $class::widget($config);

        return $this;
    }

I would suggest the following (it is BC):


    public function widget($mixed, $config = null)
    {
        /* @var $class \yii\base\Widget */
        $config['model'] = $this->model;
        $config['attribute'] = $this->attribute;
        $config['view'] = $this->form->getView();

        if(is_array($mixed)){
            $config = $mixed;
            $this->parts['{input}'] = Yii::createObject($config)->run();
        }else{
            $class = $mixed;
            $this->parts['{input}'] = $class::widget($config);
        }

        return $this;
    }
alex-code commented 8 years ago

Widget::widget() uses output buffering so your ex might break consistency.

How about this, if $class is a config array then pick out the class name.

public function widget($class, $config = [])
{
    /* @var $class \yii\base\Widget */
    $config['model'] = $this->model;
    $config['attribute'] = $this->attribute;
    $config['view'] = $this->form->getView();

    if (is_array($class) && isset($class['class'])) {
        $config = array_merge($class, $config);
        $class = $class['class'];
    }

    $this->parts['{input}'] = $class::widget($config);

    return $this;
}
dynasource commented 8 years ago

isnt Widget::widget() the same as Yii::createObject($config)->run()?

alex-code commented 8 years ago

It handles output buffering, https://github.com/yiisoft/yii2/blob/master/framework/base/Widget.php#L94

dynasource commented 8 years ago

ahh, I see, for scenario's in which echo's are done inside init. This should be prohibited in the first place ;) https://github.com/yiisoft/yii2/issues/11915

Your solution is better then!

SilverFire commented 8 years ago

@dynasource so you want to make the following code work, right?

Widget::widget([
    'class' => BarWidget::class,
    'foo' => 'baz'
]);
dynasource commented 8 years ago

correct

SilverFire commented 8 years ago

As far as I see, the only reason is to make it consistent with Yii::createObject(), right?

dynasource commented 8 years ago

definately. After making many, many form widgets, this one is always surprising because of it being inconsistent with other object & array mappings like with Yii::createObject()