Элементы input и textarea

Для работы с элементами ввода, в частности, с элементами input, select, textarea, применяется директива v-model, которая устанавливает двустороннюю привязку между элементом ввода и свойством объекта Vue. При этом v-model игнорирует значения атрибутов value, checked и selected, которые имеются у элементов ввода.

Например, используем ряд базовых элементов input:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
</head>
<body>
    <div id="app">
        <label>Логин</label>
        <input type="text" v-model="login" placeholder="Введите логин" class="form-control" /><br>
        <label>Пароль</label>
        <input type="password" v-model="password" placeholder="Введите пароль" class="form-control" /><br>
        <label>Возраст</label>
        <input type="number" v-model="age" min="18" placeholder="Введите возраст" class="form-control" /><br>
        <label>Дата регистрации</label><br>
        <input type="date" v-model="date" placeholder="Введите дату" class="form-control" />
        <br>
        <div>
            <h3>Введенная информация</h3>
            <p>Логин: {{ login }}</p>
            <p>Пароль: {{ password }}</p>
            <p>Возраст: {{ age }}</p>
            <p>Дата регистрации: {{ date }}</p>
        </div>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                login: '',
                password: '',
                date: '',
                age: 22
            }
        })
    </script>
</body>
</html>

textarea

Элемент textarea позволяет вводить многострочный текст и также связывается со свойством во Vue через директиву v-model:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
</head>
<body>
    <div id="app">
        <label>Введите комментарий</label>
        <textarea v-model="comment" class="form-control"></textarea>
        <br>
        <div>
            <h3>Комментарий</h3>
            <p style="white-space: pre-line">{{ comment }}</p>
        </div>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                comment: 'Комментарий...'
            }
        })
    </script>
</body>
</html>

В то же время есть некоторые особенности по работе с textarea. Прежде всего, если используется директива v-model, то внутри textarea мы не можем поместить текст с помощью интерполяции:

<textarea v-model="comment" class="form-control">{{ comment }}</textarea>

И кроме того, при вводе текста в textarea с помощью клавиши Enter мы можем переносить строки. Чтобы переносы строк сохранялись при выводе текста на страницу, необходимо применять соответствующие стили css:

<p style="white-space: pre-line">{{ comment }}</p>

Флажки (Checkbox)

Флажки представляют элементы управления, которые могут находиться в двух состояниях: отмеченном и неотмеченном.

Одиночный флажок может быть привязан к логическому значению true или false:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
</head>
<body>
    <div id="app">
        <input type="checkbox" id="checkbox" v-model="checked">
        <label for="checkbox">{{ checked }}</label>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                checked: true
            }
        })
    </script>
</body>
</html>

По умолчанию для отмеченного состояния используется значение true, а для неотмеченного - false. Но вместо них можно определить свои собственные значения для обоих состояний и между этими значениями переключаться:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
</head>
<body>
    <div id="app">
        <input type="checkbox" v-model="light" v-bind:true-value="on" v-bind:false-value="off" />
        <span v-if="light === on">Выключить</span>
        <span v-else>Включить</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                on: true,
                off: false,
                light: true
            }
        })
    </script>
</body>
</html>

Вместо значений true и false флажок привязывается к одному из свойств on или off. С помощью атрибута v-bind:true-value="on" отмеченное состояние будет сопоставляться со свойством on. Соответственно в неотмеченном состоянии флажок приобретает значение off. А само выбранное значение попадает в свойство light.

Привязка к массиву

Также группа флажков может быть привязана к одному массиву. В этом случае при отметке флажка его значение попадает в массив:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
</head>
<body>
    <div id="app">
        <input type="checkbox" value="Tom" v-model="selectedUsers">
        <label>Tom</label><br>
        <input type="checkbox" value="Bob" v-model="selectedUsers">
        <label>Bob</label><br>
        <input type="checkbox" value="Sam" v-model="selectedUsers">
        <label>Sam</label><br>
        <input type="checkbox" value="Alice" v-model="selectedUsers">
        <label>Alice</label><br>
        <span>Выбрано: {{ selectedUsers }}</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                selectedUsers: []
            }
        })
    </script>
</body>
</html>

В данном случае 4 флажка привязаны к массиву selectedUsers. Отметив определенный флажок, мы добавим его значение в массив.

Привязка к объекту

В примере выше значение каждого флажка представляло некоторую строку. Но также флажок может быть привязан к целому объекту. Для динамической привязки у элемента HTML применяется атрибут v-bind:value:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
</head>
<body>
    <div id="app">
        <template v-for="user in users">
            <input type="checkbox" v-bind:value="user" v-model="selectedUsers">
            <label>{{ user.name }}</label><br>
        </template>
        <ul>
            <li v-for="user in selectedUsers">{{ user.name }} - {{ user.age }}</li>
        </ul>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                users: [
                    { name: 'Tom', age: 22 },
                    { name: 'Bob', age: 25 },
                    { name: 'Sam', age: 28 },
                    { name: 'Alice', age: 26 }
                ],
                selectedUsers: []
            }
        })
    </script>
</body>
</html>

Здесь динамически для каждого объекта в массиве формируется флажок, а при выборе флажка объект попадет в массив selectedUsers.


Переключатели (radiobutton)

Переключатели или радиокнопки позволяют определить группу альтернативных вариантов, из которых одномоментно пользователь может выбрать только один. Переключатели привязываются к одному свойству. При выборе переключателя связанное свойство получает выбранное значение:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
</head>
<body>
    <div id="app">
        <input type="radio" value="Tom" v-model="user">
        <label>Tom</label>
        <br>
        <input type="radio" value="Bob" v-model="user">
        <label>Bob</label>
        <br>
        <input type="radio" value="Sam" v-model="user">
        <label>Sam</label>
        <br>
        <span>Выбрано: {{ user }}</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                user: ''
            }
        })
    </script>
</body>
</html>

Привязка к объекту

Также каждый из переключателей может быть привязан к сложному объекту. В этом случае используется атрибут v-bind:value. Результатом выбора соответственно также будет сложный объект:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
</head>
<body>
    <div id="app">
        <input type="radio" v-bind:value="{name: 'Tom', age: 22}" v-model="user">
        <label>Tom</label>
        <br>
        <input type="radio" v-bind:value="{name: 'Bob', age: 25}" v-model="user">
        <label>Bob</label>
        <br>
        <input type="radio" v-bind:value="{name: 'Sam', age: 28}" v-model="user">
        <label>Sam</label>
        <br>
        <span>Выбрано: {{ user.name }} - {{ user.age }}</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                user: {}
            }
        })
    </script>
</body>
</html>

Привязка к массиву объектов

В случае выше было бы более оптимально хранить данные в массиве и динамически создавать по элементам массива группу радиокнопок:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
</head>
<body>
    <div id="app">
        <template v-for="user in users">
            <input type="radio" v-bind:value="user" v-model="selectedUser">
            <label>{{ user.name }}</label><br>
        </template>
        <span v-if="selectedUser !== null">Выбрано: {{ selectedUser.name }} - {{ selectedUser.age }}</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                users: [
                    { name: 'Tom', age: 22 },
                    { name: 'Bob', age: 25 },
                    { name: 'Sam', age: 28 },
                    { name: 'Alice', age: 26 }
                ],
                selectedUser: null
            }
        })
    </script>
</body>
</html>

Список select

Элемент select позволяет создать список с возможностью одиночного и множественного выбора.

Список с одиночным выбором

Выпадающий список с одиночным выбором можно привязать к свойству Vue, которое хранит выбранный элемент:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
</head>
<body>
    <div id="app">
        <select v-model="user">
            <option>Tom</option>
            <option>Bob</option>
            <option>Sam</option>
        </select>
        <span>Выбрано: {{ user }}</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                user: ''
            }
        })
    </script>
</body>
</html>

Список с множественным выбором

Список select с множественным выбором можно связать с массивом, в который попадут все выбранные значения:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
</head>
<body>
    <div id="app">
        <select v-model="users" multiple>
            <option>Tom</option>
            <option>Bob</option>
            <option>Sam</option>
            <option>Alice</option>
        </select>
        <span>Выбрано: {{ users }}</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                users: []
            }
        })
    </script>
</body>
</html>

Привязка к массиву объектов

Нередко источником для элементов списка служит массив, элементы которого нередко представляют сложные объекты. Для динамического создания списка из массива применяется директива v-for, а для привязки значения к элементу списка - атрибут v-bind:value:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
</head>
<body>
    <div id="app">
        <select v-model="selectedUser">
            <option v-for="user in users" v-bind:value="user.name">{{ user.name }}</option>
        </select>
        <span>Выбрано: {{ selectedUser }}</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                users: [
                    { name: 'Tom', age: 22 },
                    { name: 'Bob', age: 25 },
                    { name: 'Sam', age: 28 },
                    { name: 'Alice', age: 26 }
                ],
                selectedUser: ''
            }
        })
    </script>
</body>
</html>

В данном случае в списке отображается значение свойства name объекта из массива и это же свойство name будет использоваться в качестве значения при выборе элемента. Однако мы можем выбирать и весь объект в целом:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
</head>
<body>
    <div id="app">
        <select v-model="selectedUser">
            <option v-for="user in users" v-bind:value="user">{{ user.name }}</option>
        </select>
        <span v-if="selectedUser !== null">Выбрано: {{ selectedUser.name }} - {{ selectedUser.age }}</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                users: [
                    { name: 'Tom', age: 22 },
                    { name: 'Bob', age: 25 },
                    { name: 'Sam', age: 28 },
                    { name: 'Alice', age: 26 }
                ],
                selectedUser: null
            }
        })
    </script>
</body>
</html>

В данном случае выбранный объект из массива будет попадать в свойство selection.

Привязка к объектам в списке с множественным выбором

Аналогично можно установить привязку к объектам в списке с множественным выбором. В этом случае выбранные элементы попадут в массив:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
</head>
<body>
    <div id="app">
        <select v-model="selectedUsers" multiple>
            <option v-for="user in users" v-bind:value="user">{{ user.name }}</option>
        </select>
        <h3>Выбранные объекты</h3>
        <ul>
            <li v-for="user in selectedUsers">{{ user.name }} - {{ user.age }}</li>
        </ul>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                users: [
                    { name: 'Tom', age: 22 },
                    { name: 'Bob', age: 25 },
                    { name: 'Sam', age: 28 },
                    { name: 'Alice', age: 26 }
                ],
                selectedUsers: null
            }
        })
    </script>
</body>
</html>

Модификаторы

Для управленя вводом с элементов форм можно использовать модификаторы.

.lazy

По умолчанию директива v-model обновляет связанные с полем ввода данные при каждом вызове события input. То есть при вводе каждого символа в текстовое поле будут изменяться связанные данные. Но вместо этого мы также можем вызывать обновление не после события input, а после события change. То есть связанные данные будут обновляться только после того, как текстовое поле потеряет фокус. Для этого применяется модификатор .lazy:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
</head>
<body>
    <div id="app">
        <input type="text" v-model.lazy="name" />
        <span>Введено: {{ name }}</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                name: ''
            }
        })
    </script>
</body>
</html>

.number

Модификатор .number позволяет автоматически конвертировать при вводе вводимое значение в число. Поскольку даже если мы установим у поля input атрибут type="number", то такое поле все равно будет возвращать строку:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
</head>
<body>
    <div id="app">
        <input v-model.number="age" type="number">
        <span>Введено: {{ age }}</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                age: 0
            }
        })
    </script>
</body>
</html>

.trim

Модификатор .trim автоматически обрезает начальные и концевые пробелы при вводе строки:

<!DOCTYPE html>
<html>
<head>
    <title>Vue.js</title>
    <meta charset="utf-8" />
</head>
<body>
    <div id="app">
        <input v-model.trim="message">
        <span>Введено: {{message}}</span>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#app',
            data: {
                message: ''
            }
        })
    </script>
</body>
</html>

Объединение модификаторов

Также можно объединять модификаторы:

<input v-model.lazy.trim="message">
<input v-model.lazy.number="age" type="number">