10. Widgets | application structure | Yii Chinese document 2.0.x

Posted by JesperBisgaard on Mon, 31 Jan 2022 23:24:21 +0100

Widget

The widget is in view Reusable units used in, using object-oriented method to create complex and configurable user interface units. For example, the date selector widget can generate a sophisticated date selector that allows users to select dates. You only need to insert the following code in the view:

<?php
use yii\jui\DatePicker;
?>
<?= DatePicker::widget(['name' => 'date']) ?>

Yii provides many excellent widgets, such as [[yii\widgets\ActiveForm|active form]], [[yii\widgets\Menu|menu]], jQuery UI widgetsTwitter Bootstrap widgets . Next, let's introduce the basic knowledge of widgets. If you want to understand a widget, please refer to the corresponding class API document.

Working with widgets

Widgets are basically views In view, you can call the [[yii\base\Widget::widget()]] method to use widgets. This method uses to configure Array initializes the widget and returns the rendered result of the widget. For example, the following code inserts a date selector widget, which is configured to use Russian, and the content of the input box is from of $model_ Date attribute value.

<?php
use yii\jui\DatePicker;
?>
<?= DatePicker::widget([
    'model' => $model,
    'attribute' => 'from_date',
    'language' => 'ru',
    'dateFormat' => 'php:Y-m-d',
]) ?>

Some widgets can use data content in [[yii\base\Widget::begin()]] and [[yii\base\Widget::end()]] calls. For example, the following code uses the [[yii\widgets\ActiveForm]] widget to generate a login form. The widget will generate the start tag and end tag of < form > at the execution of begin() and end(), and any code in the middle will also be rendered.

<?php
use yii\widgets\ActiveForm;
use yii\helpers\Html;
?>

<?php $form = ActiveForm::begin(['id' => 'login-form']); ?>

    <?= $form->field($model, 'username') ?>

    <?= $form->field($model, 'password')->passwordInput() ?>

    <div class="form-group">
        <?= Html::submitButton('Login') ?>
    </div>

<?php ActiveForm::end(); ?>

Note that unlike calling [[yii\base\Widget::widget()]] to return rendering results, calling the [[yii\base\Widget::begin()]] method returns a widget instance that can build widget content.

Note: some widgets will be used when calling [[yii\base\Widget::end()]] Output buffer To adjust the closed content. Therefore, it is better to call [[yii\base\Widget::begin()]] and [[yii\base\Widget::end()]] in the same view file. Failure to follow this rule may result in unexpected output.

Configure global defaults

The global default values of widgets can be configured through DI container:

\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]);

For more information, see Dependency injection container "Application in practice" section .

Create widget

You can create widgets in two different ways as needed.

1: Using the widget() method

Inherit the [[yii\base\Widget]] class and override the [[yii\base\Widget::init()]] and / or [[yii\base\Widget::run()]] methods to create widgets. Typically, the init () method handles widget properties, and the run () method contains the code that the widget generates the rendered result. The rendered result can be "output" directly or returned as a string through the run () method.

In the following code, HelloWidget encodes and displays the value assigned to the message attribute. If the attribute is not assigned, it will display "Hello World" by default.

namespace app\components;

use yii\base\Widget;
use yii\helpers\Html;

class HelloWidget extends Widget
{
    public $message;

    public function init()
    {
        parent::init();
        if ($this->message === null) {
            $this->message = 'Hello World';
        }
    }

    public function run()
    {
        return Html::encode($this->message);
    }
}

To use this widget, simply use the following code in the view:

<?php
use app\components\HelloWidget;
?>
<?= HelloWidget::widget(['message' => 'Good morning']) ?>

Sometimes widgets need to render a lot of content. Although you can embed the content in the run() method, a better way is to put the content into one view The file is then called [[yii\base\Widget::render()] to render the view file, for example:

public function run()
{
    return $this->render('hello');
}

2: Use the begin() and end() methods

This is similar to the above, with slight differences. Here is another kind of HelloWidget that can be used in the begin() and end() calls. The HTML encoded content is then displayed.

namespace app\components;

use yii\base\Widget;
use yii\helpers\Html;

class HelloWidget extends Widget
{
    public function init()
    {
        parent::init();
        ob_start();
    }

    public function run()
    {
        $content = ob_get_clean();
        return Html::encode($content);
    }
}

As shown above, the PHP output buffer is started in init(), and all output contents between init() and run() methods will be obtained, processed and returned in run().

Info: when you call [[yii\base\Widget::begin()]]], a new widget instance will be created and the init() method will be called at the end of construction, and the run() method will be called at end() to output the returned results.

The following code shows how to use this HelloWidget:

<?php
use app\components\HelloWidget;
?>
<?php HelloWidget::begin(); ?>

    sample content that may contain one or more <strong>HTML</strong> <pre>tags</pre>

    If this content grows too big, use sub views

    For e.g.

    <?php echo $this->render('viewfile'); // Note: here render() method is of class \yii\base\View as this part of code is within view file and not in Widget class file ?>

<?php HelloWidget::end(); ?>

By default, the view of the widget should be stored in the WidgetPath/views directory, which represents the directory where the widget class file is located. If the widget class file is under @ app/components, the above example will render @ app/components / views / Hello PHP view file. You can override the [[yii\base\Widget::getViewPath()]] method to customize the path where the view file is located.

Best practices

Widgets reuse view code in an object-oriented manner.

When creating widgets, you still need to follow the MVC pattern. Usually, the logic code is in the widget class and the display content is in the view Yes.

Widgets should be designed independently, that is, when using a widget, it can be discarded directly without additional processing. However, when widgets need external resources, such as CSS, JavaScript, pictures, etc., it will be difficult. Fortunately, Yii provides them Resource package To solve this problem.

When a widget contains only view code, it and view Very similar. In fact, in this case, the only difference is that the widget is a reusable class, and the view is just a normal PHP script used in the application.

This article was first published in LearnKu.com On the website.