How to use “ng-model” in AngularJS with EXAMPLES

โšก Smart Summary

ng-model in AngularJS binds an input control directly to a property on $scope, keeping the view and the model synchronised in both directions. The sections below cover the attribute, three working examples, and the errors beginners hit most.

  • ๐Ÿ”— Two-Way Binding: ng-model pushes user input into the $scope property and pushes controller changes back into the control automatically.
  • ๐Ÿ“ Textarea Binding: Bind a multi-line string to a textarea and use the \n escape sequence to force line breaks in the rendered value.
  • โ˜‘๏ธ Checkbox State: A checkbox bound with ng-model stores a boolean, so true renders the box as checked and false leaves it clear.
  • ๐Ÿ“‹ Dropdown Lists: Populate a select element with ng-options and bind the chosen item to a separate model property.
  • โš ๏ธ Common Failure: Binding a select to the same object that supplies its option text overwrites that object on the first selection.
  • ๐Ÿ› ๏ธ Validation Hooks: ng-model adds ng-pristine, ng-dirty, ng-valid and ng-invalid classes that drive conditional styling and form checks.

What is ng-model in AngularJS?

ng-model is a directive in AngularJS that represents the model, and its primary purpose is to bind the “view” to the “model”. Whatever the user types into a control is written straight into a property on $scope, and whatever the controller writes to that property is pushed straight back into the control.

For example, suppose you wanted to present a simple page to the end user like the one shown below, which asks the user to enter the “First name” and “Last name” in textboxes. And then you wanted to ensure that you store the information the user has entered in your data model.

You can use the ng-model directive to map the text box fields of “First name” and “Last name” to your data model. The directive will ensure that the data in the “view” and that of your “model” are kept in sync the whole time, without a single line of event-handling code.

โš ๏ธ Version note: AngularJS (the 1.x branch) reached end of life on 31 December 2021 and no longer receives security patches. The examples below still run, but in modern Angular the same two-way binding is written as [(ngModel)] and requires the FormsModule.

The ng-model Attribute

As discussed in the section above, the ng-model attribute is used to bind the data in your model to the view presented to the user.

The ng-model attribute is used for,

  1. Binding controls such as input, text area and select elements in the view into the model.
  2. Providing a validation behavior โ€” for example, a validation can be added to a text box so that only numeric characters can be entered.
  3. Maintaining the state of the control. By state, we mean that the control and the data are always kept in sync: if the value of the data changes, the value in the control changes automatically, and vice versa.
  4. Exposing that state as CSS classes. AngularJS adds ng-pristine, ng-dirty, ng-valid and ng-invalid to every control carrying an ng-model, which is what makes conditional styling of forms straightforward.

With the attribute understood, the next step is to apply it to the three control types you will meet most often.

How to use ng-model

1) Text Area

The text area tag is used to define a multi-line text input control. The text area can hold an unlimited number of characters, and the text renders in a fixed-width font.

So now let’s look at a simple example of how we can add the ng-model directive to a text area control. In this example, we want to show how we can pass a multiline string from the controller to the view and attach that value to the text area control.

<!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 Explanation:

  1. The ng-model directive attaches the member variable called “pDescription” to the “textarea” control. The “pDescription” variable holds the text that is passed on to the text area control. The rows="4" and cols="50" attributes simply size the control so that the multi-line text is displayed properly.
  2. The member variable “pDescription” is assigned a multiline value. The \n escape sequence inside the string is what forces the text onto a second line when the textarea renders it.

Output:

From the output, it is clear that the multiline text assigned in the controller is displayed in the text area control, split across two lines exactly where the \n sits.

2) Input elements

The ng-model directive works with ordinary input elements as well. Below we bind a text box and two checkboxes at the same time, so you can see how ng-model handles a string value and a boolean value side by side.

<!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 Explanation:

  1. The ng-model directive attaches the member variable “pname” to the text input control, and the properties Topic.Controller and Topic.Models to the two checkbox controls.
  2. In the controller, “pname” is given the string “Guru99”, and the “Topic” object is given two boolean members. A checkbox bound with ng-model always reads and writes a boolean, which is why true renders the box as checked and false leaves it clear.

Output:

From the output,

  • It can be clearly seen that the value assigned to the pname variable is “Guru99”.
  • Since the first bound value is true, the checkbox is marked for the “Controller” checkbox. Likewise, since the second value is false, the checkbox is not marked for the “Models” checkbox.

3) Select element from Dropdown

The ng-model directive can also be applied to the select element, so that the item the user chooses is stored in the model.

Here we will have a text input which holds the name “Guru99”, and a select list with two list items, “Controller” and “Models”.

โš ๏ธ Correction: The screenshot above shows the original listing, which bound the select element to the very same Topics object that supplied the option text. The moment a user picks an option, AngularJS overwrites Topics with the selected string and both options vanish. The corrected listing below keeps the list in one property and the selection in another, and uses ng-options to build the list.

<!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 Explanation:

  1. The text input is bound to pName, and the select element is bound to selectedTopic. Because the select has its own model property, choosing an option never disturbs the list itself.
  2. The Topics array holds the two values “Controller” and “Models”. The ng-options expression walks that array and renders one option per entry, so adding a third topic requires no change to the markup.
  3. selectedTopic is pre-set to the first entry, which is what makes the dropdown open with a sensible default instead of a blank row.

Output:

From the output, it can be seen that the value assigned to the pName variable is “Guru99”, and the select control offers the options “Controller” and “Models”. Working examples aside, bindings do sometimes refuse to update, and the reasons are worth knowing.

Why ng-model Bindings Sometimes Fail

Most reported ng-model problems are not bugs in AngularJS but consequences of how scopes and primitives work.

The classic case is a binding placed inside a directive that creates a child scope, such as ng-repeat, ng-if or ng-switch. Writing ng-model="name" there creates a shadow copy on the child scope, so the parent never sees the edit. Binding to a property of an object instead โ€” ng-model="user.name" โ€” keeps every scope pointing at the same reference. This is the reason experienced AngularJS developers insist on a dot in every ng-model expression.

Two further causes account for most of the rest:

  • Missing controller or module: if ng-app or ng-controller is misspelt, the binding silently renders nothing rather than raising an error.
  • Value changed outside AngularJS: a value set from a jQuery handler or a setTimeout callback lands outside the digest cycle, so the view does not refresh until $scope.$apply() runs.

Checking those three things resolves the large majority of bindings that appear not to work.

FAQs

ng-bind is one-way: it prints a model value into an element. ng-model is two-way and works only on form controls, so user input flows back into the model as well as out of it.

Add ng-model-options, for example ng-model-options=”{ debounce: 500 }”. AngularJS then waits half a second after the last keystroke before updating the model, which is useful for search boxes that trigger a request.

Largely, yes. AI assistants rewrite ng-model as [(ngModel)] and add the FormsModule import. Reactive forms, custom parsers and $formatters pipelines still need manual review, because Angular models them very differently.

AI tools check the usual suspects fast: a primitive bound inside a child scope, a misspelt controller name, and a value assigned outside the digest cycle. Each produces a silent failure rather than a console error.

Only input type=”number” is parsed to a numeric value. A type=”text” control always yields a string, so comparisons with === fail. Convert explicitly, or switch the input type.

Summarize this post with: