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

larnu committed
4 5 6 7
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
8 9 10 11 12 13 14 15

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

larnu committed
16 17 18 19
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.
Larnu committed
20 21 22

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

larnu committed
23 24 25 26 27
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
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

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

larnu committed
43 44 45 46 47
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 generará las etiquetas '<form>' 
de apertura y cierre donde sean llamados 'begin()' y 'end()', respectivamente. Cualquier cosa que este en medio será 
representado como tal.
Larnu committed
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67

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

larnu committed
68 69 70
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.
Larnu committed
71 72 73

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

larnu committed
74 75 76 77 78
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
79

larnu committed
80 81
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
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116

```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']) ?>
```

larnu committed
117 118
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
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

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

larnu committed
142 143
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()'.
Larnu committed
144

larnu committed
145 146 147
> 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
148 149 150 151 152 153 154 155 156 157 158 159 160 161

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

larnu committed
162 163 164
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:
Larnu committed
165 166 167 168 169 170 171 172

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

larnu committed
173 174 175 176 177
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
178

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

pana1990 committed
181
Los widgets son una manera orientada a objetos de reutilizar código de las vistas.
Larnu committed
182

larnu committed
183 184
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).
Larnu committed
185

larnu committed
186 187 188 189
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 
[asset bundles](structure-asset-bundles.md) que pueden ser utilizados para resolver el problema.
Larnu committed
190

larnu committed
191 192 193
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.