# Classe assistante Html ¶

Toutes les applications Web génèrent un grand nombre de balises HTML. Si le code HTML est statique, il peut être créé efficacement sous forme de mélange de code PHP et de code HTML dans un seul fichier, mais lorsqu'il est généré dynamiquement, cela commence à être compliqué à gérer sans une aide supplémentaire. Yii fournit une telle aide sous la forme de la classe assistante Html, qui offre un jeu de méthodes statiques pour manipuler les balises Html les plus courantes, leurs options et leur contenu.

> Note : si votre code HTML est presque statique, il vaut mieux utiliser HTML directement. Il n'est pas nécessaire d'envelopper tout dans des appels aux méthodes de la classe assistante Html.

## Les bases ¶

Comme la construction de code HTML dynamique en concaténant des chaînes de caractère peut très vite tourner à la confusion, Yii fournit un jeu de méthodes pour manipuler les options de balises et construire des balises s'appuyant sur ces options.

### Génération de balises ¶

Le code pour générer une balise ressemble à ceci :

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

Le premier argument est le nom de la balise. Le deuxième est le contenu qui apparaît entre l'ouverture de la balise et sa fermeture. Notez que nous utilisons `Html::encode` – c'est parce que le contenu n'est pas encodé automatiquement pour permetre l'utilisation de HTML quand c'est nécessaire. Le troisième est un tableau d'options HTML ou, en d'autres mots, les attributs de la balise. Dans ce tableau, la clé est le nom de l'attribut (comme `class`, `href` ou `target`) et la valeur est sa valeur.

Le code ci-dessus génère le code HTML suivant :

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

Dans le cas où vous avez simplement besoin d'ouvrir ou de fermer la balise, vous pouvez utiliser les méthodes `Html::beginTag()` et `Html::endTag()`.

Des options sont utilisées dans de nombreuses méthodes de la classe assistante Html et de nombreux composants graphiques (widgets). Dans tous ces cas, il y a quelques manipulations supplémentaires à connaître :

- Si une valeur est `null`, l'attribut correspondant n'est pas rendu.
- Les attributs du type booléen sont traités comme des attributs booléens .
- Les valeurs des attributs sont encodés HTML à l'aide de la méthode Html::encode().

- Si la valeur d'un attribut est un tableau, il est géré comme suit :

  - Si l'attribut est un attribut de donnée tel que listé dans yii\helpers\Html::$dataAttributes, tel que `data` ou `ng`, une liste d'attributs est rendue, un pour chacun des élément dans le tableau de valeurs. Par exemple, `'data' => ['id' => 1, 'name' => 'yii']` génère `data-id="1" data-name="yii"`; et `'data' => ['params' => ['id' => 1, 'name' => 'yii'], 'status' => 'ok']` génère `data-params='{"id":1,"name":"yii"}' data-status="ok"`. Notez que dans le dernier exemple le format JSON est utilisé pour rendre le sous-tableau.
  - Si l'attribut n'est PAS un attribut de donnée, la valeur est encodée JSON. Par exemple, `['params' => ['id' => 1, 'name' => 'yii']` génère `params='{"id":1,"name":"yii"}'`.

### Formation des classes et des styles CSS ¶

Lors de la construction des options pour des balises HTML, nous démarrons souvent avec des valeurs par défaut qu'il faut modifier. Afin d'ajouter ou de retirer une classe, vous pouvez utiliser ce qui suit :

    $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);

    // si la valeur de $type est 'success' le rendu sera
    // <div class="btn btn-success">Pwede na</div>

Vous pouvez spécifier de multiples classe CSS en utilisant le tableau de styles également :

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

    echo Html::tag('div', 'Save', $options);
    // rend '<div class="btn btn-default">Save</div>'

Vous pouvez aussi utiliser le tableau de styles pour ajouter ou retirer des classes :

    $options = ['class' => 'btn'];

    if ($type === 'success') {
        Html::addCssClass($options, ['btn-success', 'btn-lg']);
    }

    echo Html::tag('div', 'Save', $options);
    // rend '<div class="btn btn-success btn-lg">Save</div>'

`Html::addCssClass()` empêche la duplication, vous n'avez donc pas à vous préoccuper de savoir si une classe apparaît deux fois :

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

    Html::addCssClass($options, 'btn-default'); // class 'btn-default' is already present

    echo Html::tag('div', 'Save', $options);
    // rend '<div class="btn btn-default">Save</div>'

Si l'option classe CSS est spécifiée en utilisant le tableau de styles, vous pouvez utiliser une clé nommée pour indiquer le but logique de la classe. Dans ce cas, une classe utilisant la même clé dans le tableau de styles passé à `Html::addClass()` est ignorée :

    $options = [
        'class' => [
            'btn',
            'theme' => 'btn-default',
        ]
    ];

    Html::addCssClass($options, ['theme' => 'btn-success']); // la clé 'theme' est déjà utilisée

    echo Html::tag('div', 'Save', $options);
    // rend '<div class="btn btn-default">Save</div>'

Les styles CSS peuvent être définis d'une façon similaire en utilisant l'attribut `style` :

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

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

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

Lors de l'utilisation de addCssStyle(), vous pouvez spécifier soit un tableau de paires clé-valeur qui correspond aux propriétés CSS noms et valeurs, soit une chaîne de caractères telle que `width: 100px; height: 200px;`. Ces formats peuvent être convertis de l'un en l'autre en utilisant les méthodes cssStyleFromArray() et cssStyleToArray(). La méthode removeCssStyle() accepte un tableau de propriétés à retirer. S'il s'agit d'une propriété unique, elle peut être spécifiée sous forme de chaîne de caractères.

### Encodage et décodage du contenu ¶

Pour que le contenu puisse être affiché en HTML de manière propre et en toute sécurité, les caractères spéciaux du contenu doivent être encodés. En PHP, cela s'obtient avec htmlspecialchars et htmlspecialchars_decode. Le problème rencontré en utilisant ces méthodes directement est que vous devez spécifier l'encodage et des options supplémentaires tout le temps. Comme ces options restent toujours les mêmes et que l'encodage doit correspondre à celui de l'application pour éviter les problèmes de sécurité, Yii fournit deux méthodes compactes et faciles à utiliser :

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

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

## Formulaires ¶

Manipuler des formulaires dans le code HTML est tout à fait répétitif et sujet à erreurs. À cause de cela, il existe un groupe de méthodes pour aider à les manipuler.

> Note : envisagez d'utiliser ActiveForm dans le cas où vous avez affaire à des modèles et que ces derniers doivent être validés.

### Création de formulaires ¶

Les formulaires peut être ouverts avec la méthode beginForm() comme ceci :

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

Le premier argument est l'URL à laquelle le formulaire sera soumis. Il peut être spécifié sous la forme d'une route Yii et de paramètres acceptés par Url::to(). Le deuxième est la méthode à utiliser. `post` est la méthode par défaut. Le troisième est un tableau d'options pour la balise form. Dans ce cas, nous modifions l'encodage des données du formulaire dans la requête POST en `multipart/form-data`, ce qui est requis pour envoyer des fichiers.

La fermeture du formulaire se fait simplement par :

    <?= Html::endForm() ?>

### Boutons ¶

Pour générer des boutons, vous pouvez utiliser le code suivant :

    <?= Html::button('Pressez-mo!', ['class' => 'teaser']) ?>
    <?= Html::submitButton('Envoyer', ['class' => 'submit']) ?>
    <?= Html::resetButton('Ré-initialiser', ['class' => 'reset']) ?>

Le premier argument pour les trois méthodes est l'intitulé du bouton, le deuxième est un tableau d'options. L'intitulé n'est pas encodé, mais si vous affichez des données en provenance de l'utilisateur, encodez les avec Html::encode().

### Champs d'entrée ¶

Il y a deux groupes de méthodes d'entrée de données. Celles qui commencent par `active`, est qui sont appelées entrées actives, et celles qui ne commencent pas par ce mot. Les entrées actives prennent leurs données dans le modèle à partir des attributs spécifiés, tandis que pour les entrées régulières, les données sont spécifiées directement.

Les méthodes les plus génériques sont :

    type, nom de l'entrée, valeur de l'entrée, options
    <?= Html::input('text', 'username', $user->name, ['class' => $username]) ?>

    type, modèle, nom de l'attribut du modèle, options
    <?= Html::activeInput('text', $user, 'name', ['class' => $username]) ?>

Si vous connaissez le type de l'entrée à l'avance, il est plus commode d'utiliser les méthodes raccourcis :

- 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()

Les listes radio et les boîtes à cocher sont un peu différentes en matière de signature de méthode :

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

Les listes déroulantes et les boîtes listes peuvent être rendues comme suit :

    <?= 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')) ?>

Le premier argument est le nom de l'entrée, le deuxième est la valeur sélectionnée actuelle et le troisième est un tableau de paires clé-valeur, dans lequel la clé est la valeur d'entrée dans la liste et la valeur est l'étiquette qui correspond à cette valeur dans la liste.

Si vous désirez que des choix multiples soient sélectionnables, vous pouvez utiliser la liste à sélection multiples (checkbox list) :

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

Sinon utilisez la liste radio :

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

### Étiquettes et erreurs ¶

Comme pour les entrées, il existe deux méthodes pour générer les étiquettes de formulaire. Celles pour les entrées « actives » qui prennent leurs étiquettes dans le modèle, et celles « non actives » qui sont étiquetées directement :

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

Pour afficher les erreurs de formulaire à partir d'un modèle ou sous forme de résumé pour un modèle, vous pouvez utiliser :

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

Pour afficher une erreur individuellement :

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

### Nom et valeur des entrées ¶

Il existe deux méthodes pour obtenir des noms, des identifiants et des valeurs pour des champs d'entrée basés sur un modèle. Elles sont essentiellement utilisées en interne, mais peuvent être pratiques quelques fois :

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

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

    // my first post
    echo Html::getAttributeValue($post, 'title');

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

Dans ce qui précède, le premier argument est le modèle, tandis que le deuxième est l'expression d'attribut. Dans sa forme la plus simple, l'expression est juste un nom d'attribut, mais il peut aussi s'agir d'un nom d'attribut préfixé et-ou suffixé par des index de tableau, ce qui est essentiellement le cas pour des entrées tabulaires :

- `[0]content` est utilisé dans des entrées de données tabulaires pour représenter l'attribut `content` pour le premier modèle des entrées tabulaires ;
- `dates[0]` représente le premier élément du tableau de l'attribut `dates` ;
- `[0]dates[0]` représente le premier élément du tableau de l'attribut `dates` pour le premier modèle des entrées tabulaires.

Afin d'obtenir le nom de l'attribut sans suffixe ou préfixe, vous pouvez utiliser ce qui suit :

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

## Styles et scripts ¶

Il existe deux méthodes pour générer les balises enveloppes des styles et des scripts :

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

    Produit

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

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

    Produit

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

Si vous désirez utiliser utiliser un style externe d'un fichier CSS :

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

    génère

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

Le premier argument est l'URL. Le deuxième est un tableau d'options. En plus des options normales, vous pouvez spécifier :

- `condition` pour envelopper `<link` dans des commentaires conditionnels avec la condition spécifiée. Nous espérons que vous n'aurez jamais besoin de commentaires conditionnels ;
- `noscript` peut être défini à `true` pour envelopper `<link` dans une balise `<noscript>` de façon à ce qu'elle soit incluse seulement si le navigateur ne prend pas en charge JavaScript ou si l'utilisateur l'a désactivé.

Pour lier un fichier JavaScript :

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

Se passe comme avec CSS, le premier argument spécifie l'URL du fichier à inclure. Les options sont passées via le deuxième argument. Dans les options vous pouvez spécifier `condition` de la même manière que dans les options pour un fichier CSS (méthode `cssFile`).

## Hyperliens ¶

Il y a une méthode commode pour générer les hyperliens :

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

Le premier argument est le titre. Il n'est pas encodé, mais si vous utilisez des données entrées par l'utilisateur, vous devez les encoder avec `Html::encode()`. Le deuxième argument est ce qui se retrouvera dans l'attribut `href` de la balise `<a`.

Voir Url::to() pour les détails sur les valeurs acceptées. Le troisième argument est un tableau pour les attributs de la balise.

Si vous devez générer des liens `mailto`, vous pouvez utiliser le code suivant :

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

## Images ¶

Pour générer une balise image, utilisez le code suivant :

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

    qui génère

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

En plus des alias, le premier argument accepte les routes, les paramètres et les URL, tout comme Url::to().

## Listes ¶

Les listes non ordonnées peuvent être générées comme suit :

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

Pour une liste ordonnée, utilisez plutôt `Html::ol()`.