helper-html.md 13.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
Html helper
===========

Every web application generates lots of HTML markup. If markup is static, it could be done efficiently by
[mixing PHP and HTML in a single file](http://php.net/manual/en/language.basic-syntax.phpmode.php) but when it is
generated dynamically it is starting to get tricky to handle it without extra help. Yii provides such help in a form
of Html helper which provides a set of static methods for handling commonly used HTML tags, their options and content.

> Note: If your markup is nearly static it's better to use HTML directly. There's no need to wrap absolutely everything
  with Html helper calls.

larnu committed
12

13
## Basics <span id="basics"></span>
14 15 16 17 18

Since building dynamic HTML by string concatenation is getting messy very fast, Yii provides a set of methods to
manipulate tag options and build tags based on these options.


19
### Generating Tags <span id="generating-tags"></span>
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

The code generating a tag looks like the following:

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

The first argument is tag name. Second one is content to be enclosed between the start and end tags. Note that we are
using `Html::encode`. That's because content isn't encoded automatically to allow using HTML when needed. Third one is an
array of HTML options or, in other words, tag attributes. In this array key is the name of the attribute such as `class`,
`href` or `target` and a value is its value.

The code above will generate the following HTML:

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

In case you need just start tag or just closing tag you can use `Html::beginTag()` and `Html::endTag()` methods.

Options are used in many methods of Html helper and various widgets. In all these cases there is some extra handling to
know about:
larnu committed
42

43 44 45 46 47 48 49 50 51
- If a value is null, the corresponding attribute will not be rendered.
- Attributes whose values are of boolean type will be treated as
  [boolean attributes](http://www.w3.org/TR/html5/infrastructure.html#boolean-attributes).
- The values of attributes will be HTML-encoded using [[yii\helpers\Html::encode()|Html::encode()]].
- The "data" attribute could receive an array. In this case, it will be "expanded" and a list data attributes will be
  rendered i.e. `'data' => ['id' => 1, 'name' => 'yii']` becomes `data-id="1" data-name="yii"`.
- The "data" attribute could receive JSON. It is handled the same way as array i.e.
  `'data' => ['params' => ['id' => 1, 'name' => 'yii'], 'status' => 'ok']` becomes
  `data-params='{"id":1,"name":"yii"}' data-status="ok"`.
larnu committed
52

53

54
### Forming CSS Classes and Styles <span id="forming-css"></span>
55 56 57 58 59 60 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

When building options for HTML tag we're often starting with defaults which we need to modify. In order to add or
remove CSS class you can use the following:

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

// in case of $type of 'success' it will render
// <div class="btn btn-success">Pwede na</div>
```

In order to do the same with styles for the `style` attribute:

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

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

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

When using [[yii\helpers\Html::addCssStyle()|addCssStyle()]] you can specify either an array of key-value pairs
corresponding to CSS property names and values or a string such as `width: 100px; height: 200px;`. These formats
could be converted there and forth by using [[yii\helpers\Html::cssStyleFromArray()|cssStyleFromArray()]] and
[[yii\helpers\Html::cssStyleToArray()|cssStyleToArray()]]. The [[yii\helpers\Html::removeCssStyle()|removeCssStyle()]]
method accepts an array of properties to remove. If it's going to be a single property it could be specified as string.

larnu committed
91

92
### Encoding and Decoding Content <span id="encoding-and-decoding-content"></span>
93 94 95 96 97 98 99 100 101 102 103 104 105

In order for content to be displayed properly and securely in HTML special characters in the content should be encoded.
In PHP it's done with [htmlspecialchars](http://www.php.net/manual/en/function.htmlspecialchars.php) and
[htmlspecialchars_decode](http://www.php.net/manual/en/function.htmlspecialchars-decode.php). The issue with using
these methods directly is that you have to specify encoding and extra flags all the time. Since flags are the same
all the time and encoding should match the one of the application in order to prevent security issues, Yii provides two
compact and simple to use methods:

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

$decodedUserName = Html::decode($userName);
larnu committed
106
```
107

108

109
## Forms <span id="forms"></span>
110 111 112 113 114 115

Dealing with forms markup is quite repetitive and error prone. Because of that there is a group of methods to help
dealing with them.

> Note: consider using [[yii\widgets\ActiveForm|ActiveForm]] in case you deal with models and need validation.

larnu committed
116

117
### Creating Forms <span id="creating-forms"></span>
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135

Form could be opened with [[yii\helpers\Html::beginForm()|beginForm()]] method like the following:

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

First argument is the URL form will be submitted to. It could be specified in form of Yii route and parameters accepted
by [[yii\helpers\Url::to()|Url::to()]]. Second one is method to use. `post` is default. Third one is array of options
for the form tag. In this case we're changing the way of encoding form data in POST request to `multipart/form-data`.
It is required in order to upload files.

Closing form tag is simple:

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

larnu committed
136

137
### Buttons <span id="buttons"></span>
138 139 140 141 142 143 144 145 146 147 148 149 150

In order to generate buttons you can use the following code:

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

First argument for all three methods is button title and the second one is options. Title isn't encoded so if you're
getting data from end user, encode it with [[yii\helpers\Html::encode()|Html::encode()]].


151
### Input Fields <span id="input-fields"></span>
152 153 154 155 156 157 158 159

There are two groups on input methods. The ones starting with `active` and called active inputs and the ones not starting
with it. Active inputs are taking data from model and attribute specified while in case of regular input data is specified
directly.

The most generic methods are:

```php
160
type, input name, input value, options
161 162
<?= Html::input('text', 'username', $user->name, ['class' => $username]) ?>

163
type, model, model attribute name, options
164 165 166 167 168 169 170 171 172 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
<?= Html::activeInput('text', $user, 'name', ['class' => $username]) ?>
```

If you know input type in advance it's more convenient to use shortcut methods:

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

Radios and checkboxes are a bit different in terms of method signature:

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

Dropdown list and list box could be rendered like the following:

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

First argument is the name of the input, second is the value that's currently selected and third is key-value pairs where
array key is list value and array value is list label.
larnu committed
200

201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
If you want multiple choices to be selectable, checkbox list is a good match:

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

If not, use radio list:

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


216
### Labels and Errors <span id="labels-and-errors"></span>
217 218 219 220 221 222 223 224

Same as inputs there are two methods for generating form labels. Active that's taking data from the model and non-active
that accepts data directly:

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

226
In order to display form errors from a model or models as a summary you could use:
227 228 229 230 231 232 233 234 235 236

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

To display individual error:

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

238

239
### Input Names and Values <span id="input-names-and-values"></span>
larnu committed
240

241
There are methods to get names, ids and values for input fields based on the model. These are mainly used internally
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
but could be handy sometimes:

```php
// 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]');
```

258
In the above first argument is the model while the second one is attribute expression. In its simplest form it's
259 260 261 262 263 264 265 266 267 268 269 270 271
attribute name but it could be an attribute name prefixed and/or suffixed with array indexes which are mainly used
for tabular input:

- `[0]content` is used in tabular data input to represent the "content" attribute for the first model in tabular input;
- `dates[0]` represents the first array element of the "dates" attribute;
- `[0]dates[0]` represents the first array element of the "dates" attribute for the first model in tabular input.

In order to get attribute name without suffixes or prefixes one can use the following:

```php
// dates
echo Html::getAttributeName('dates[0]');
```
larnu committed
272 273


274
## Styles and Scripts <span id="styles-and-scripts"></span>
275 276 277 278 279 280

There two methods to generate tags wrapping embedded styles and scripts:

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

281
Gives you
282 283 284 285 286 287

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


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

288
Gives you
289 290 291 292 293 294 295 296 297

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

If you want to link external style from CSS file:

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

298
generates
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319

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

First argument is the URL. Second is an array of options. Additionally to regular options you could specify:

- `condition` to wrap `<link` with conditional comments with condition specified. Hope you won't need conditional
  comments ever ;)
- `noscript` could be set to `true` to wrap `<link` with `<noscript>` tag so it will be included only when there's
  either no JavaScript support in the browser or it was disabled by the user.

To link JavaScript file:

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

Same as with CSS first argument specifies link to the file to be included. Options could be passed as the second argument.
In options you can specify `condition` in the same way as in options for `cssFile`.
larnu committed
320 321


322
## Hyperlinks <span id="hyperlinks"></span>
323 324

There's a method to generate hyperlink conveniently:
larnu committed
325

326 327 328 329 330 331 332 333 334
```php
<?= Html::a('Profile', ['user/view', 'id' => $id], ['class' => 'profile-link']) ?>
```

The first argument is the title. It's not encoded so if you're using data got from user you need to encode it with
`Html::encode()`. Second argument is what will be in `href` of `<a` tag. See [Url::to()](helper-url.md) for details on
what values it accepts. Third argument is array of tag properties.

In you need to generate `mailto` link you can use the following code:
larnu committed
335

336 337 338
```php
<?= Html::mailto('Contact us', 'admin@example.com') ?>
```
larnu committed
339 340


341
## Images <span id="images"></span>
342 343

In order to generate image tag use the following:
larnu committed
344

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

348
generates
349 350 351 352 353 354

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

Aside [aliases](concept-aliases.md) the first argument can accept routes, parameters and URLs. Same way as
[Url::to()](helper-url.md) does.
larnu committed
355 356


357
## Lists <span id="lists"></span>
larnu committed
358

359 360 361 362 363 364 365 366 367 368 369 370
Unordered list could be generated like the following:

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

371
In order to get ordered list use `Html::ol()` instead.