helper-html.md 14.7 KB
Newer Older
larnu committed
1 2 3
Clase auxiliar Html (Html helper)
=================================

4 5 6
Todas las aplicaciones web generan grandes cantidades de marcado HTML (HTML markup). Si el marcado es estático, se
puede realizar de forma efectiva
[mezclando PHP y HTML en un mismo archivo](http://php.net/manual/es/language.basic-syntax.phpmode.php) pero cuando se
7 8
generan dinámicamente empieza a complicarse su gestión sin ayuda extra. Yii ofrece esta ayuda en forma de una clase auxiliar Html
que proporciona un conjunto de métodos estáticos para gestionar las etiquetas HTML más comúnmente usadas, sus opciones y contenidos.
larnu committed
9

10
> Nota: Si el marcado es casi estático, es preferible usar HTML directamente. No es necesario encapsularlo todo con
larnu committed
11 12
llamadas a la clase auxiliar Html.

13 14
## Lo fundamental <a name="basics"></a>

larnu committed
15

16 17
Teniendo en cuenta que la construcción de HTML dinámico mediante la concatenación de cadenas de texto se complica
rápidamente, Yii proporciona un conjunto de métodos para manipular las opciones de etiquetas y la construcción de las
larnu committed
18 19
mismas basadas en estas opciones.

20
### Generación de etiquetas <a name="generating-tags"></a>
larnu committed
21 22 23 24 25 26 27

El código de generación de etiquetas es similar al siguiente:

```php
<?= Html::tag('p', Html::encode($user->name), ['class' => 'username']) ?>
```

28
El primer argumento es el nombre de la etiqueta. El segundo es el contenido que se ubicará entre la etiqueta de
29 30 31
apertura y la de cierre. Hay que tener en cuenta que estamos usando `Html::encode`. Esto es debido a que el contenido
no se codifica automáticamente para permitir usar HTML cuando se necesite. La tercera opción es un array de opciones
HTML o, en otras palabras, los atributos de las etiquetas. En este array la clave representa el nombre del atributo
larnu committed
32 33
como podría ser `class`, `href` o `target` y el valor es su valor.

34
El código anterior generará el siguiente HTML:
larnu committed
35 36 37 38 39

```html
<p class="username">samdark</p>
```

40
Si se necesita solo la apertura o el cierre de una etiqueta, se pueden usar los métodos `Html::beginTag()` y
larnu committed
41 42
`Html::endTag()`.

43
Las opciones se usan en muchos métodos de la clase auxiliar Html y en varios widgets. En todos estos casos hay cierta
larnu committed
44 45 46
gestión adicional que se debe conocer:

- Si un valor es `null`, el correspondiente atributo no se renderizará.
47
- Los atributos cuyos valores son de tipo booleano serán tratados como
larnu committed
48
  [atributos booleanos](http://www.w3.org/TR/html5/infrastructure.html#boolean-attributes).
49
- Los valores de los atributos se codificarán en HTML usando [[yii\helpers\Html::encode()|Html::encode()]].
50 51
- El atributo "data" puede recibir un array. En este caso, se "expandirá" y se renderizará una lista de atributos
  `data` ej. `'data' => ['id' => 1, 'name' => 'yii']` se convierte en `data-id="1" data-name="yii"`.
52
- El atributo "data" puede recibir un JSON. Se gestionará de la misma manera que un array ej.
53
  `'data' => ['params' => ['id' => 1, 'name' => 'yii'], 'status' => 'ok']` se convierte en
larnu committed
54 55
  `data-params='{"id":1,"name":"yii"}' data-status="ok"`.

56
### Formación de clases y estilos dinámicamente <a name="forming-css"></a>
larnu committed
57

58
Cuando se construyen opciones para etiquetas HTML, a menudo nos encontramos con valores predeterminados que hay que
larnu committed
59 60 61 62 63 64 65 66 67 68 69 70
modificar. Para añadir o eliminar clases CSS se puede usar el siguiente ejemplo:

```php
$options = ['class' => 'btn btn-default'];

if ($type === 'success') {
    Html::removeCssClass($options, 'btn-default');
    Html::addCssClass($options, 'btn-success');
}

echo Html::tag('div', 'Pwede na', $options);

71
// cuando $type sea 'success' se renderizará
larnu committed
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
// <div class="btn btn-success">Pwede na</div>
```

Para hacer lo mismo con los estilos para el atributo `style`:

```php
$options = ['style' => ['width' => '100px', 'height' => '100px']];

// devuelve style="width: 100px; height: 200px; position: absolute;"
Html::addCssStyle($options, 'height: 200px; positon: absolute;');

// devuelve style="position: absolute;"
Html::removeCssStyle($options, ['width', 'height']);
```

87 88 89 90 91
Cuando se usa [[yii\helpers\Html::addCssStyle()|addCssStyle()]] se puede especificar si un array de pares clave-valor
corresponde a nombres y valores de la propiedad CSS correspondiente o a una cadena de texto como por ejemplo
`width: 100px; height: 200px;`. Estos formatos se pueden "hacer" y "deshacer" usando
[[yii\helpers\Html::cssStyleFromArray()|cssStyleFromArray()]] y
[[yii\helpers\Html::cssStyleToArray()|cssStyleToArray()]]. El método
92 93 94 95
[[yii\helpers\Html::removeCssStyle()|removeCssStyle()]] acepta un array de propiedades que se eliminarán. Si sólo se
eliminara una propiedad, se puede especificar como una cadena de texto.

## Codificación y Decodificación del contenido <a name="encoding-and-decoding-content"></a>
larnu committed
96 97


98 99 100
Para que el contenido se muestre correctamente y de forma segura con caracteres especiales HTML el contenido debe ser
codificado. En PHP esto se hace con [htmlspecialchars](http://www.php.net/manual/es/function.htmlspecialchars.php) y
[htmlspecialchars_decode](http://www.php.net/manual/es/function.htmlspecialchars-decode.php). El problema con el uso
101 102
de estos métodos directamente es que se tiene que especificar la codificación y opciones extra cada vez. Ya que las
opciones siempre son las mismas y la codificación debe coincidir con la de la aplicación para prevenir problemas de
larnu committed
103 104 105 106 107 108 109 110 111
seguridad, Yii proporciona dos métodos simples y compactos:

```php
$userName = Html::encode($user->name);
echo $userName;

$decodedUserName = Html::decode($userName);
```

112 113
## Formularios <a name="forms"></a>

larnu committed
114

115
El trato con el marcado de formularios es una tarea repetitiva y propensa a errores. Por esto hay un grupo de métodos
larnu committed
116 117
para ayudar a gestionarlos.

118
> Nota: hay que considerar la opción de usar [[yii\widgets\ActiveForm|ActiveForm]] en caso de que se gestionen
larnu committed
119 120
formularios que requieran validaciones.

121
### Creando formularios <a name="creating-forms"></a>
larnu committed
122

123
Se puede abrir un formulario con el método [[yii\helpers\Html::beginForm()|beginForm()]] como se muestra a
larnu committed
124 125 126 127 128 129
continuación:

```php
<?= Html::beginForm(['order/update', 'id' => $id], 'post', ['enctype' => 'multipart/form-data']) ?>
```

130 131
El primer argumento es la URL a la que se enviarán los datos del formulario. Se puede especificar en formato de ruta
de Yii con los parámetros aceptados por [[yii\helpers\Url::to()|Url::to()]]. El segundo es el método que se usará.
132 133
`post` es el método predeterminado. El tercero es un array de opciones para la etiqueta `form`. En este caso cambiamos
el método de codificación del formulario de `data` en una petición POST a `multipart/form-data`. Esto se requiere
larnu committed
134 135 136 137 138 139 140 141
cuando se quieren subir archivos.

El cierre de la etiqueta `form` es simple:

```php
<?= Html::endForm() ?>
```

142
### Botones <a name="buttons"></a>
larnu committed
143 144 145 146 147 148 149 150 151

Para generar botones se puede usar el siguiente código:

```php
<?= Html::button('Press me!', ['class' => 'teaser']) ?>
<?= Html::submitButton('Submit', ['class' => 'submit']) ?>
<?= Html::resetButton('Reset', ['class' => 'reset']) ?>
```

152
El primer argumento para los tres métodos es el título del botón y el segundo son las opciones. El título no está
153
codificado pero si se usan datos recibidos por el usuario, deben codificarse mediante
larnu committed
154 155
[[yii\helpers\Html::encode()|Html::encode()]].

156
### Inputs <a name="input-fields"></a>
larnu committed
157

158 159
Hay dos grupos en los métodos input. Unos empiezan con `active` y se llaman inputs activos y los otros no empiezan
así. Los inputs activos obtienen datos del modelo y del atributo especificado y los datos de los inputs normales se
larnu committed
160 161 162 163 164
especifica directamente.

Los métodos más genéricos son:

```php
larnu committed
165
type, input name, input value, options
larnu committed
166 167
<?= Html::input('text', 'username', $user->name, ['class' => $username]) ?>

larnu committed
168
type, model, model attribute name, options
larnu committed
169 170 171
<?= Html::activeInput('text', $user, 'name', ['class' => $username]) ?>
```

172
Si se conoce el tipo de input de antemano, es conveniente usar los atajos de los métodos:
larnu committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202

- [[yii\helpers\Html::buttonInput()]]
- [[yii\helpers\Html::submitInput()]]
- [[yii\helpers\Html::resetInput()]]
- [[yii\helpers\Html::textInput()]], [[yii\helpers\Html::activeTextInput()]]
- [[yii\helpers\Html::hiddenInput()]], [[yii\helpers\Html::activeHiddenInput()]]
- [[yii\helpers\Html::passwordInput()]] / [[yii\helpers\Html::activePasswordInput()]]
- [[yii\helpers\Html::fileInput()]], [[yii\helpers\Html::activeFileInput()]]
- [[yii\helpers\Html::textarea()]], [[yii\helpers\Html::activeTextarea()]]

Los botones de opción (Radios) y las casillas de verificación (checkboxes) se especifican de forma un poco diferente:

```php
<?= Html::radio('agree', true, ['label' => 'I agree']);
<?= Html::activeRadio($model, 'agree', ['class' => 'agreement'])

<?= Html::checkbox('agree', true, ['label' => 'I agree']);
<?= Html::activeCheckbox($model, 'agree', ['class' => 'agreement'])
```

Las listas desplegables (dropdown list) se pueden renderizar como se muestra a continuación:

```php
<?= Html::dropDownList('list', $currentUserId, ArrayHelper::map($userModels, 'id', 'name')) ?>
<?= Html::activeDropDownList($users, 'id', ArrayHelper::map($userModels, 'id', 'name')) ?>

<?= Html::listBox('list', $currentUserId, ArrayHelper::map($userModels, 'id', 'name')) ?>
<?= Html::activeListBox($users, 'id', ArrayHelper::map($userModels, 'id', 'name')) ?>
```

203
El primer argumento es el nombre del input, el segundo es el valor seleccionado actualmente y el tercero es el array
204
de pares clave-valor donde la clave es la lista de valores y el valor del array es la lista a mostrar.
larnu committed
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219

Si se quiere habilitar la selección múltiple, se puede usar la lista seleccionable (checkbox list):

```php
<?= Html::checkboxList('roles', [16, 42], ArrayHelper::map($roleModels, 'id', 'name')) ?>
<?= Html::activeCheckboxList($user, 'role', ArrayHelper::map($roleModels, 'id', 'name')) ?>
```

Si no, se puede usar la lista de opciones (radio list):

```php
<?= Html::radioList('roles', [16, 42], ArrayHelper::map($roleModels, 'id', 'name')) ?>
<?= Html::activeRadioList($user, 'role', ArrayHelper::map($roleModels, 'id', 'name')) ?>
```

220
### Etiquetas y Errores <a name="labels-and-errors"></a>
larnu committed
221

222 223
De forma parecida que en los inputs hay dos métodos para generar etiquetas. El activo que obtiene los datos del modelo y
el no-activo que acepta los datos directamente:
larnu committed
224 225 226 227 228 229

```php
<?= Html::label('User name', 'username', ['class' => 'label username']) ?>
<?= Html::activeLabel($user, 'username', ['class' => 'label username'])
```

230
Para mostrar los errores del formulario de un modelo o modelos a modo de resumen puedes usar:
larnu committed
231 232 233 234 235 236 237 238 239 240 241

```php
<?= Html::errorSummary($posts, ['class' => 'errors']) ?>
```

Para mostrar un error individual:

```php
<?= Html::error($post, 'title', ['class' => 'error']) ?>
```

242
### Input Names y Values <a name="input-names-and-values"></a>
larnu committed
243

244
Existen métodos para obtener names, IDs y values para los campos de entrada (inputs) basados en el modelo. Estos se
larnu committed
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
usan principalmente internamente pero a veces pueden resultar prácticos:

```php
// Post[title]
echo Html::getInputName($post, 'title');

// post-title
echo Html::getInputId($post, 'title');

// mi primer post
echo Html::getAttributeValue($post, 'title');

// $post->authors[0]
echo Html::getAttributeValue($post, '[0]authors[0]');
```

261
En el ejemplo anterior, el primer argumento es el modelo y el segundo es un atributo de expresión. En su forma más
262
simple es su nombre de atributo pero podría ser un nombre de atributo prefijado y/o añadido como sufijo con los
larnu committed
263 264
indices de un array, esto se usa principalmente para mostrar inputs en formatos de tablas:

265
- `[0]content` se usa en campos de entrada de datos en formato de tablas para representar el atributo "content" para
larnu committed
266 267 268 269 270 271 272 273 274 275 276
  el primer modelo del input en formato de tabla;
- `dates[0]` representa el primer elemento del array del atributo "dates";
- `[0]dates[0]` representa el primer elemento del array del atributo "dates" para el primer modelo en formato de tabla.

Para obtener el nombre de atributo sin sufijos o prefijos se puede usar el siguiente código:

```php
// dates
echo Html::getAttributeName('dates[0]');
```

277 278
## Estilos y scripts <a name="styles-and-scripts"></a>

larnu committed
279 280 281 282 283 284

Existen dos métodos para generar etiquetas que envuelvan estilos y scripts incrustados (embebbed):

```php
<?= Html::style('.danger { color: #f00; }') ?>

larnu committed
285
Genera
larnu committed
286 287 288 289 290

<style>.danger { color: #f00; }</style>

<?= Html::script('alert("Hello!");', ['defer' => true]);

larnu committed
291
Genera
larnu committed
292 293 294 295 296 297 298 299 300

<script defer>alert("Hello!");</script>
```

Si se quiere enlazar un estilo externo desde un archivo CSS:

```php
<?= Html::cssFile('@web/css/ie5.css', ['condition' => 'IE 5']) ?>

larnu committed
301
genera
larnu committed
302 303 304 305 306 307

<!--[if IE 5]>
    <link href="http://example.com/css/ie5.css" />
<![endif]-->
```

308
El primer argumento es la URL. El segundo es un array de opciones. Adicionalmente, para regular las opciones se puede
larnu committed
309 310
especificar:

311
- `condition` para envolver `<link` con los comentarios condicionales con condiciones especificas. Esperamos que sean
larnu committed
312
  necesarios los comentarios condicionales ;)
313
- `noscript` se puede establecer como `true` para envolver `<link` con la etiqueta `<noscript>` por lo que el sólo se
larnu committed
314 315 316 317 318 319 320 321
  incluirá si el navegador no soporta JavaScript o si lo ha deshabilitado el usuario.

Para enlazar un archivo JavaScript:

```php
<?= Html::jsFile('@web/js/main.js') ?>
```

322 323
Es igual que con las CSS, el primer argumento especifica el enlace al fichero que se quiere incluir. Las opciones se
pueden pasar como segundo argumento. En las opciones se puede especificar `condition` del mismo modo que se puede usar
larnu committed
324 325
para `cssFile`.

326 327
## Enlaces <a name="hyperlinks"></a>

larnu committed
328 329 330 331 332 333 334

Existe un método para generar hipervínculos a conveniencia:

```php
<?= Html::a('Profile', ['user/view', 'id' => $id], ['class' => 'profile-link']) ?>
```

335
El primer argumento es el título. No está codificado por lo que si se usan datos enviados por el usuario se tienen que
336
codificar usando `Html::encode()`. El segundo argumento es el que se introducirá en `href` de la etiqueta `<a`. Se
337
puede consultar [Url::to()](helper-url.md) para obtener más detalles de los valores que acepta. El tercer argumento es
larnu committed
338 339 340 341 342 343 344 345
un array de las propiedades de la etiqueta.

Si se requiere generar enlaces de tipo `mailto` se puede usar el siguiente código:

```php
<?= Html::mailto('Contact us', 'admin@example.com') ?>
```

346 347
## Imagenes <a name="images"></a>

larnu committed
348 349 350 351 352 353

Para generar una etiqueta de tipo imagen se puede usar el siguiente ejemplo:

```php
<?= Html::img('@web/images/logo.png', ['alt' => 'My logo']) ?>

larnu committed
354
genera
larnu committed
355 356 357 358

<img src="http://example.com/images/logo.png" alt="My logo" />
```

359
Aparte de los [alias](concept-aliases.md) el primer argumento puede aceptar rutas, parámetros y URLs. Del mismo modo
larnu committed
360 361
que [Url::to()](helper-url.md).

362 363
## Listas <a name="lists"></a>

larnu committed
364 365 366 367 368 369 370 371 372 373 374 375 376

Las listas desordenadas se puede generar como se muestra a continuación:

```php
<?= Html::ul($posts, ['item' => function($item, $index) {
    return Html::tag(
        'li',
        $this->render('post', ['item' => $item]),
        ['class' => 'post']
    );
}]) ?>
```

larnu committed
377
Para generar listas ordenadas se puede usar `Html::ol()` en su lugar.