Как использовать «ng-model» в AngularJS с ПРИМЕРАМИ

⚡ Умное резюме

ng-model в AngularJS напрямую привязывает элемент управления ввода к свойству в $scope, обеспечиваяping Представление и модель синхронизированы в обоих направлениях. В разделах ниже рассматриваются атрибуты, три работающих примера и наиболее распространенные ошибки, с которыми сталкиваются новички.

  • 🔗 Двусторонняя переплетка: ng-model передаёт пользовательский ввод в свойство $scope и автоматически передаёт изменения контроллера обратно в элемент управления.
  • ???? Привязка текстового поля: Привяжите многострочную строку к текстовому полю и используйте управляющую последовательность \n для принудительного переноса строк в отображаемом значении.
  • ☑️ Состояние флажка: Флажок, связанный с ng-model, хранит логическое значение, поэтому значение true отображает флажок как отмеченный, а значение false — как неотмеченный.
  • 📋 Выпадающие списки: Заполните элемент select атрибутом ng-options и привяжите выбранный элемент к отдельному свойству модели.
  • ⚠️ Распространенная неисправность: Привязка выпадающего списка к тому же объекту, который предоставляет текст для его варианта выбора, перезаписывает этот объект при первом выборе.
  • 🇧🇷 Хуки проверки: ng-model добавляет классы ng-pristine, ng-dirty, ng-valid и ng-invalid, которые управляют условным стилем и проверками форм.

Что такое ng-модель в AngularJS?

ng-model — это директива в AngularJS, представляющая модель, и её основная цель — связать «представление» с «моделью». Всё, что пользователь вводит в элемент управления, записывается непосредственно в свойство. $scopeИ всё, что контроллер записывает в это свойство, напрямую передаётся обратно в элемент управления.

Например, предположим, вы хотите показать пользователю простую страницу, подобную показанной ниже, на которой ему предлагается ввести «Имя» и «Фамилия» в текстовые поля. И затем вы хотите убедиться, что информация, введенная пользователем, сохраняется в вашей модели данных.

Вы можете использовать директиву ng-model для сопоставления текстовых полей «Имя» и «Фамилия» с вашей моделью данных. Эта директива обеспечит постоянную синхронизацию данных в «представлении» и вашей «модели» без единой строки кода обработки событий.

⚠️ Примечание к версии: Поддержка AngularJS (ветка 1.x) прекратилась 31 декабря 2021 года, и обновления безопасности больше не выпускаются. Приведенные ниже примеры по-прежнему работают, но в современном Angular та же двусторонняя привязка реализована следующим образом: [(ngModel)] и требует наличия модуля FormsModule.

Атрибут ng-model

Как обсуждалось в разделе выше, атрибут ng-model используется для привязки данных вашей модели к представлению, отображаемому пользователю.

Атрибут ng-model используется для:

  1. Привязка элементов управления, таких как поля ввода, текстовые поля и элементы выбора в представлении, к модели.
  2. Предоставление механизма проверки данных — например, можно добавить проверку для текстового поля, чтобы в него можно было вводить только числовые символы.
  3. Поддержание состояния элемента управления. Под состоянием мы подразумеваем постоянную синхронизацию элемента управления и данных: если значение данных изменяется, значение в элементе управления автоматически изменяется, и наоборот.
  4. Предоставление доступа к этому состоянию через CSS-классы. AngularJS добавляет ng-pristine, ng-dirty, ng-valid и ng-invalid к каждому элементу управления, имеющему атрибут ng-model, что упрощает условное оформление форм.

Поняв суть атрибута, следующим шагом будет его применение к трем типам элементов управления, с которыми вы будете сталкиваться чаще всего.

Как использовать ng-модель

1) Текстовая область

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

Теперь давайте рассмотрим простой пример того, как можно добавить директиву ng-model к элементу управления текстового поля. В этом примере мы хотим показать, как можно передать многострочную строку из контроллера в представление и прикрепить это значение к элементу управления текстового поля.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <script src="https://code.angularjs.org/1.8.3/angular.js"></script>
</head>
<body>
<h1>Guru99 Global Event</h1>

<div ng-app="DemoApp" ng-controller="DemoCtrl">
    <form>
        Topic Description:<br><br>
        <textarea rows="4" cols="50" ng-model="pDescription"></textarea>
    </form>
</div>

<script>
    var app = angular.module('DemoApp', []);
    app.controller('DemoCtrl', function($scope) {
        $scope.pDescription = "This topic looks at how Angular JS works \nModels in Angular JS";
    });
</script>
</body>
</html>

Code Объяснение:

  1. директива ng-модели прикрепляет переменную-член с именем «p»Descript«ion» к элементу управления «textarea». «p»DescriptПеременная ion содержит текст, передаваемый в элемент управления текстовой областью. rows="4" и cols="50" Атрибуты просто изменяют размер элемента управления таким образом, чтобы многострочный текст отображался корректно.
  2. Переменная члена «p»Descriptиону присваивается многострочное значение. \n Экранирующая последовательность внутри строки — это то, что заставляет текст переходить на вторую строку при его отображении в текстовом поле.

Выход:

Из выходных данных видно, что многострочный текст, заданный в контроллере, отображается в текстовом поле, разделённый на две строки точно там, где... \n сидит.

2) Элементы ввода

Директива ng-model работает и с обычными элементами ввода. Ниже мы одновременно связываем текстовое поле и два флажка, чтобы вы могли увидеть, как ng-model обрабатывает строковое значение и логическое значение одновременно.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <script src="https://code.angularjs.org/1.8.3/angular.js"></script>
</head>
<body>
<h1>Guru99 Global Event</h1>

<div ng-app="DemoApp" ng-controller="DemoCtrl">
    <form>
        Topic Description:<br><br>
        Name : <input type="text" ng-model="pname"><br>
        Topic :<br>
        <input type="checkbox" ng-model="Topic.Controller">Controller<br>
        <input type="checkbox" ng-model="Topic.Models">Models
    </form>
</div>

<script>
    var app = angular.module('DemoApp', []);
    app.controller('DemoCtrl', function($scope) {
        $scope.pname = "Guru99";

        $scope.Topic = {
            Controller: true,
            Models: false
        };
    });
</script>
</body>
</html>

Code Объяснение:

  1. Директива ng-model прикрепляет переменную-член «pname» к элементу управления текстового ввода и его свойствам. Topic.Controller и Topic.Models к двум флажкам.
  2. В контроллере переменной «pname» присваивается строка «Guru99”, а объекту «Topic» присваиваются два логических значения. Флажок, связанный с ng-model, всегда считывает и записывает логическое значение, поэтому true отображает флажок как отмеченный. false Это проясняет ситуацию.

Выход:

Из вывода,

  • Чётко видно, что значение, присвоенное pname переменная — «Guru99 ".
  • Поскольку первое граничное значение равно trueФлажок установлен для пункта «Контроллер». Аналогично, поскольку второе значение равно falseПри этом флажок «Модели» не отмечен.

3) Выберите элемент из раскрывающегося списка.

Директиву ng-model также можно применить к элементу select, чтобы выбранный пользователем элемент сохранялся в модели.

Здесь у нас будет текстовое поле ввода, в котором будет храниться имя "Guru99”, и выпадающий список с двумя пунктами: «Контроллер» и «Модели».

⚠️ Исправление: На скриншоте выше показан исходный список, в котором элемент select был привязан к тому же самому элементу. Topics Объект, который предоставил текст для выбора варианта. В тот момент, когда пользователь выбирает вариант, AngularJS перезаписывает его. Topics При выборе строки оба параметра исчезают. В исправленном списке ниже список сохраняется в одном свойстве, а выделение — в другом, и используется ng-options для составления списка.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <script src="https://code.angularjs.org/1.8.3/angular.js"></script>
</head>
<body>
<h1>Guru99 Global Event</h1>

<div ng-app="DemoApp" ng-controller="DemoCtrl">
    <form>
        Topic Description:<br><br>
        Name : <input type="text" ng-model="pName"><br>
        Topic :<br>
        <!-- Topics holds the list; selectedTopic holds the choice -->
        <select ng-model="selectedTopic" ng-options="t for t in Topics"></select>
    </form>
</div>

<script>
    var app = angular.module('DemoApp', []);
    app.controller('DemoCtrl', function($scope) {
        $scope.pName = "Guru99";

        $scope.Topics = ["Controller", "Models"];
        $scope.selectedTopic = $scope.Topics[0];
    });
</script>
</body>
</html>

Code Объяснение:

  1. Поле ввода текста привязано к pNameи элемент выбора привязан к selectedTopicПоскольку у выпадающего списка есть собственное свойство модели, выбор варианта никогда не изменяет сам список.
  2. Topics Массив содержит два значения: «Controller» и «Models». ng-options Выражение проходит по этому массиву и отображает один вариант для каждой записи, поэтому добавление третьей темы не требует изменения разметки.
  3. selectedTopic По умолчанию установлено первое значение, благодаря чему выпадающий список открывается с разумным значением по умолчанию, а не с пустой строкой.

Выход:

Из полученных данных видно, что значение, присвоенное pName переменная — «Guru99”, а в меню выбора элементов управления предлагаются опции «Контроллер» и «Модели». Помимо рабочих примеров, иногда привязки не обновляются, и причины этого стоит знать.

Почему иногда не удается установить связь с помощью ng-model?

Большинство сообщений о проблемах с ng-model связаны не с ошибками в AngularJS, а с особенностями работы областей видимости и примитивов.

Классический пример — это привязка, помещенная внутрь директивы, которая создает дочернюю область видимости, например: нг-повторитьng-if или ng-switch. Написание ng-model="name" Это создаёт теневую копию в дочерней области видимости, поэтому родительский элемент никогда не увидит изменения. Вместо этого можно привязаться к свойству объекта — ng-model="user.name" — обеспечивает привязку всех областей видимости к одной и той же ссылке. Именно поэтому опытные разработчики AngularJS настаивают на использовании точки в каждом выражении ng-model.

Остальная часть объясняется еще двумя причинами:

  • Отсутствует контроллер или модуль: Если название ng-app или ng-controller написано с ошибкой, привязка молча ничего не отобразит, вместо того чтобы выдать ошибку.
  • Значение изменено вне AngularJS: Значение, установленное обработчиком jQuery или функцией обратного вызова setTimeout, попадает за пределы цикла обновления данных, поэтому представление не обновляется до тех пор, пока... $scope.$apply() пробеги.

Проверка этих трех пунктов решает подавляющее большинство проблем с неработающими привязками.

Часто задаваемые вопросы (FAQ)

ng-bind — односторонний механизм: он выводит значение модели в элемент. ng-model — двусторонний механизм, работающий только с элементами управления форм, поэтому пользовательский ввод передается как обратно в модель, так и из нее.

Добавьте, например, ng-model-options: ng-model-options=”{ debounce: 500 }”. В этом случае AngularJS будет ждать полсекунды после последнего нажатия клавиши, прежде чем обновить модель, что полезно для полей поиска, которые инициируют запрос.

В основном, да. Искусственные интеллекты переписывают ng-model как [(ngModel)] и добавляют импорт FormsModule. Реактивные формы, пользовательские парсеры и конвейеры $formatters по-прежнему требуют ручной проверки, поскольку Angular моделирует их совершенно по-другому.

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

Только поле ввода типа «number» преобразуется в числовое значение. Поле ввода типа «text» всегда возвращает строку, поэтому сравнения с помощью оператора === завершаются неудачей. Преобразуйте значение явно или измените тип ввода.

Подведем итог этой публикации следующим образом: