Yii2 framework backup
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
8.1 KiB

Widgets
=======
Los _widgets_ son bloques de código reutilizables que se usan en las [vistas](structure-views.md)
para crear elementos de interfaz de usuario complejos y configurables, de forma orientada a objetos.
Por ejemplo, un _widget_ de selección de fecha puede generar un selector de fechas bonito que
permita a los usuarios seleccionar una fecha. Todo lo que hay que hacer es insertar el siguiente
código en una vista:
```php
<?php
use yii\jui\DatePicker;
?>
<?= DatePicker::widget(['name' => 'date']) ?>
```
Yii incluye un buen número de _widgets_, tales como
[[yii\widgets\ActiveForm|formulario activo]],
[[yii\widgets\Menu|menú]],
[_widgets_ de jQuery UI](https://www.yiiframework.com/extension/yiisoft/yii2-jui), y
[_widgets_ de Twitter Bootstrap](https://www.yiiframework.com/extension/yiisoft/yii2-bootstrap).
A continuación presentaremos las nociones básicas de de los _widgets_. Por favor, refiérase a la
documentación de la API de clases si quiere aprender más acerca del uso de un _widget_ en particular.
## Uso de los _widgets_ <span id="using-widgets"></span>
Los _widgets_ se usan 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 toma un _array_ de
[configuración](concept-configurations.md) para inicializar el _widget_ y devuelve la representación
resultante del _widget_. Por ejemplo, el siguiente código inserta un _widget_ de selección de fecha
configurado para usar el idioma ruso y guardar la selección en el atributo `from_date` de `$model`.
```php
<?php
use yii\jui\DatePicker;
?>
<?= DatePicker::widget([
'model' => $model,
'attribute' => 'from_date',
'language' => 'ru',
'dateFormat' => 'php:Y-m-d',
]) ?>
```
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 se llame a `begin()` y `end()`
respectivamente. Cualquier cosa que este en medio se representará tal cual.
```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_.
> Nota: Algunos _widgets_ utilizan un [búfer de salida](http://php.net/manual/es/book.outcontrol.php)
> para ajustar el contenido rodeado al invocar [[yii\base\Widget::end()]]. Por este motivo se espera
> que las llamadas a [[yii\base\Widget::begin()]] y [[yii\base\Widget::end()]] tengan lugar en el
> mismo fichero de vista.
> No seguir esta regla puede desembocar en una salida distinta a la esperada.
### Configuración de las variables globales predefinidas
Las variables globales predefinidas de un _widget_ se pueden configurar por medio del contenedor
de inyección de dependencias:
```php
\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]);
```
Consulte la [sección "Uso práctico" de la Guía del contenedor de inyección de dependencias](concept-di-container.md#practical-usage) para más detalles.
## Creación de _widgets_ <span id="creating-widgets"></span>
Para crear un _widget_, extienda la clase [[yii\base\Widget]] y sobrescriba 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 inicializa las propiedades del _widget_, mientras que el método `run()`
debería contener el código que genera la representación resultante del _widget_. La representación
resultante del método `run()` puede pasarse directamente a `echo` o devolverse como una cadena.
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 omisión.
```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']) ?>
```
Abajo se muestra una variante de `HelloWidget` que toma el contenido insertado entre las llamadas a
`begin()` y `end()`, lo codifica en HTML y posteriormente lo muestra.
```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 de PHP es iniciado en `init()` para que toda salida
entre las llamadas de `init()` y `run()` puede ser capturada, procesada y devuelta en `run()`.
> Info: Cuando llame a [[yii\base\Widget::begin()]], se creará una nueva instancia del _widget_ y se
> llamará a su método `init()` al final del constructor del _widget_. Cuando llame a
> [[yii\base\Widget::end()]], se invocará el método `run()` y el resultado que devuelva será pasado
> a `echo` por `end()`.
El siguiente código muestra cómo usar esta nueva variante de `HelloWidget`:
```php
<?php
use app\components\HelloWidget;
?>
<?php HelloWidget::begin(); ?>
contenido que puede contener <etiqueta>s
<?php HelloWidget::end(); ?>
```
A veces, un _widget_ puede necesitar representar un gran bloque de contenido. Aunque que se
podría incrustar el contenido dentro del método `run()`, es preferible ponerlo dentro de una
[vista](structure-views.md) y llamar al método [[yii\base\Widget::render()]] para representarlo.
Por ejemplo:
```php
public function run()
{
return $this->render('hello');
}
```
Por omisión, 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 ejemplo anterior representará el fichero de vista
`@app/components/views/hello.php`, suponiendo 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 contiene los ficheros de vista del _widget_.
## Buenas prácticas <span id="best-practices"></span>
Los _widgets_ son una manera orientada a objetos de reutilizar código de las vistas.
Al crear _widgets_, debería continuar suguiendo el patrón MVC. En general, se debería mantener la
lógica en las clases del widget y la presentación en las [vistas](structure-views.md).
Los _widgets_ deberían diseñarse para ser autosuficientes. Es decir, cuando se use un _widget_, se
debería poder ponerlo 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) (_asset bundles_)
que se pueden utilizar para resolver este problema.
Cuando un _widget_ sólo contiene código de vista, 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 simple script PHP que prefiere mantener dentro de su aplicación.