structure-widgets.md 7.06 KB
Newer Older
Larnu committed
1 2 3
Widgets
=======

4
Los Widgets son bloques de código reutilizables utilizados en las [vistas](structure-views.md) para crear elementos de interfaz de usuario complejos y configurables de forma orientada a objetos. Por ejemplo, widget DatePicker puede generar un DatePicker de lujo que permita a los usuarios seleccionar una fecha. Todo lo que se tiene que hacer es insertar el siguiente código en una vista.
Larnu committed
5 6 7 8 9 10 11 12 13 14 15 16

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

Hay un buen número de widgets incluidos en Yii, tales como [[yii\widgets\ActiveForm|active form]], [[yii\widgets\Menu|menu]], [Widgets de jQuery UI](widget-jui.md), [widgets de Twitter Bootstrap](widget-bootstrap.md). En adelante, introduciremos las nociones básicas acerca de los widgets. Por favor, refiérase a la documentación de la API de clases si quiere aprender más acerca de el uso de un widget en particular.

## Uso de los Widgets <a name="using-widgets"></a>

17
Los Widgets son usados principalmente en las [vistas](structure-views.md). Se puede llamar al método [[yii\base\Widget::widget()]] para usar un widget en una vista. El método obtiene un array de [configuración](concept-configurations.md) para inicializar el widget y retorna la representación resultante del widget. Por ejemplo, el siguiente código inserta un widget DatePicker que esta configurado para usar el idioma Ruso y mantener la entrada en atributo 'form_date' del '$model'.
Larnu committed
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

```php
<?php
use yii\jui\DatePicker;
?>
<?= DatePicker::widget([
    'model' => $model,
    'attribute' => 'from_date',
    'language' => 'ru',
    'clientOptions' => [
        'dateFormat' => 'yy-mm-dd',
    ],
]) ?>
```

Algunos widgets pueden coger un bloque de contenido que debería encontrarse entre la invocación de [[yii\base\Widget::begin()]] y [[yii\base\Widget::end()]]. Por ejemplo, el siguiente código usa el widget [[yii\widgets\ActiveForm]] para generar un formulario de inicio de sesión. El widget generara las etiquetas '<form>' de apertura y cierre donde sean llamados 'begin()' y 'end()', respectivamente. Cualquier cosa que este en medio será representado como tal.

```php
<?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(); ?>
```

Hay que tener en cuenta que a diferencia de [[yii\base\Widget::widget()]] que devuelve la representación resultante del widget, el método [[yii\base\Widget::begin()]] devuelve una instancia del widget que se puede usar para generar el contenido del widget.

## Creación Widgets <a name="creating-widgets"></a>

pana1990 committed
58
Para crear un widget, se debe extender a [[yii\base\Widget]] y sobrescribir los métodos [[yii\base\Widget::init()]] y/o [[yii\base\Widget::run()]]. Normalmente el método 'init()' debería contener el código que estandariza las propiedades del widget, mientras que el método 'run()' debería contener el código que genere la representación resultante del widget. La representación resultante puede ser "pintada" directamente o devuelta como una cadena por el método 'run()'.
Larnu committed
59

pana1990 committed
60
En el siguiente ejemplo, 'HelloWidget' codifica en HTML y muestra el contenido asignado a su propiedad 'message'. Si la propiedad no está establecida, mostrará "Hello World" por defecto.
Larnu committed
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95

```php
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);
    }
}
```

Para usar este widget, simplemente inserte el siguiente código en una vista:

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

pana1990 committed
96
Abajo se muestra una variante de 'HelloWidget' obtiene el contenido entre las llamadas 'begin()' y 'end()', lo codifica en HTML y posteriormente lo muestra.
Larnu committed
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121

```php
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);
    }
}
```

Como se puede observar, el búfer de salida PHP es iniciado en 'init()' por tanto cualquier salida entre las llamadas de 'init()' y 'run()' puede ser capturada, procesada y devuelta en 'run()'.

pana1990 committed
122
>Info: Cuando se llama a [[yii\base\Widget::begin()]], se creará una nueva instancia del widget y el método 'init()' será llamado al final del constructor del widget. Cuando se llama [[yii\base\Widget::end()]], el método 'run()' será llamado el resultado que devuelva será escrito por 'end()'.
Larnu committed
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145

El siguiente código muestra como usar esta nueva variante de 'HelloWidget':

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

    content that may contain <tag>'s

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

A veces, un widget puede necesitar representar una gran cantidad de contenido. Mientras que se puede incrustar el contenido dentro del método 'run()', ponerlo dentro de una [vista](structure-views.md) y llamar [[yii\base\Widget::render()]] para representarla, es un mejor enfoque. Por ejemplo:

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

pana1990 committed
146
Por defecto, las vistas para un widget deberían encontrarse en ficheros dentro del directorio 'WidgetPath/views', donde 'WidgetPath' representa el directorio que contiene el fichero de clase del widget. Por lo tanto, el anterior ejemplo representará el fichero de la vista `@app/components/views/hello.php`, asumiendo que la clase del widget se encuentre en `@app/components`. Se puede sobrescribir el método [[yii\base\Widget::getViewPath()]] para personalizar el directorio que contenga los ficheros de la vista del widget.
Larnu committed
147

pana1990 committed
148
## Mejores Prácticas <a name="best-practices"></a>
Larnu committed
149

pana1990 committed
150
Los widgets son una manera orientada a objetos de reutilizar código de las vistas.
Larnu committed
151 152 153

Cuando se crean widgets, se debería continuar manteniendo el patrón MVC. En general, se debería mantener la lógica en las clases del widget y mantener la presentación en las [vistas](structure-views.md).

154
Los widgets deberían ser diseñados para ser autónomos. Es decir, cuando se usa un widget, se debería poder poner en una vista sin hacer nada más. Esto puede resultar complicado si un widget requiere recursos externos, tales como CSS, JavaScript, imágenes, etc. Afortunadamente Yii proporciona soporte para [paquetes de recursos](structure-asset-bundles.md) que pueden ser utilizados para resolver el problema.
Larnu committed
155

pana1990 committed
156
Cuando un widget sólo contiene código de vista, este es muy similar a una [vista](structure-views.md). De hecho, en este caso, su única diferencia es que un widget es una clase redistribuible, mientras que una vista es sólo un script PHP llano que prefiere mantenerse dentro de su aplicación.