AngularJS Controllers with ng-Controller Example

โšก Smart Summary

A Controller in AngularJS holds the business logic of a screen. It receives data through the scope object, processes it, and exposes the result back to the view, keeping presentation markup free of application logic.

  • ๐ŸŽฏ Core Responsibility: A controller populates the scope object and exposes methods to the view; it does not manipulate the DOM.
  • ๐Ÿ”— Wiring: The ng-controller directive binds a named controller to an element, giving that element and its children access to the controller scope.
  • ๐Ÿ” Two-Way Binding: ng-model links a form field to a scope property, so edits in the view update the controller and the reverse.
  • ๐Ÿงฉ Methods: Functions attached to the scope separate distinct pieces of logic and are callable directly from view expressions.
  • ๐Ÿท๏ธ controllerAs Syntax: Aliasing a controller and binding to this removes ambiguity when controllers are nested inside one another.
  • ๐Ÿ“ Separation: Moving controllers into a dedicated app.js keeps the view layer independent of the logic layer.

AngularJS Controllers with ng-controller

What is Controller in AngularJS?

A Controller in AngularJS takes the data from the View, processes the data, and then sends that data across to the view which is displayed to the end user. The Controller holds your core business logic. It uses the data model, carries out the required processing, and then passes the output to the view.

โš ๏ธ Version note: AngularJS (the 1.x branch) reached end of life on 31 December 2021 and receives no further security patches. The concepts below still apply to legacy applications; in modern Angular the same role is filled by a component class rather than a controller.

Knowing what a controller is leaves one question open: how it actually communicates with the view. The next section answers that.

What Controller does from Angular’s Perspective

Following is a simple definition of the working of an AngularJS Controller:

Working of AngularJS Controller
Working of AngularJS Controller
  • The controller’s primary responsibility is to control the data which gets passed to the view. The scope and the view have two-way communication.
  • View properties and events can call functions on the scope. The snippet below shows the function($scope) declared with the controller plus an internal function returning $scope.firstName and $scope.lastName joined. In AngularJS, a function defined as a variable is a Method.

Working of AngularJS Controller

  • Data passes from the controller to the scope, and then back and forth between the scope and the view.
  • The scope exposes the model to the view. The model can be modified via methods defined on the scope, which are triggered by events from the view.
  • Controllers should not be used for manipulating the DOM. That is the job of directives.
  • Best practice is to base controllers on functionality. If you have an input form that needs a controller, create one called “form controller”.

With the mechanism understood, the next section builds a controller from an empty page.

How to Build a Basic Controller in AngularJS

Below are the steps to create a controller in AngularJS.

Step 1) Create a basic HTML Page

Before creating a controller, the basic HTML page has to be in place. The snippet below is a simple page titled “Event Registration” that references Bootstrap and AngularJS.

Build a Basic Controller in AngularJS

  1. References to the Bootstrap CSS stylesheet, used together with the Bootstrap library.
  2. A reference to the AngularJS library. Everything done with AngularJS from here on is resolved from this file.
  3. A reference to the Bootstrap library, which makes certain controls responsive.

โš ๏ธ Correction: the original loaded jQuery and stated that AngularJS depends on it. It does not. AngularJS ships with jqLite, a built-in subset of the jQuery API, and only upgrades to full jQuery if jQuery loads before it. The reference has been removed.

Step 2) Check the files and file structure

Build a Basic Controller in AngularJS

  1. Files are split into two folders as in any conventional web application: “css” for stylesheets and “lib” for JavaScript files.
  2. bootstrap.css sits in the css folder and gives the site its look and feel.
  3. angular.js is the main library, downloaded from the AngularJS site and kept in lib.
  4. app.js will contain the code for the controllers.

Step 3) Use AngularJS code to display the output

The goal here is to display the words “AngularJS” both as plain text and inside a text box when the page is opened in the browser.

Build a Basic Controller in AngularJS

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Event Registration</title>
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body>
<h1> Guru99 Global Event</h1>

<div ng-app="DemoApp" ng-controller="DemoController">
Tutorial Name : <input type="text" ng-model="tutorialName"><br>
This tutorial is {{tutorialName}}
</div>

<script src="lib/angular.js"></script>
<script>
var app = angular.module('DemoApp', []);

app.controller('DemoController', ['$scope', function($scope) {
  $scope.tutorialName = "AngularJS";
}]);
</script>
</body>
</html>

Code Explanation:

  1. ng-app marks this element as the root of an AngularJS application. Attributes prefixed with ng- are built-in directives. “DemoApp” is the name given to the application.
  2. The div carries ng-controller with the name “DemoController”, which gives that element and everything inside it access to the controller scope.
  3. ng-model creates the model binding, tying the Tutorial Name text box to the scope property tutorialName.
  4. The module DemoApp is created, and the controller assigns a default value of “AngularJS” to tutorialName.

โš ๏ธ Corrections applied. The original listing declared chrset="UTF 8", which is neither a valid attribute nor a valid encoding name, and loaded AngularJS twice โ€” once from the CDN and once from lib/angular.js. Loading the library twice re-registers the module system and produces unpredictable behaviour. The dependency array annotation ['$scope', function($scope){โ€ฆ}] was also added, without which the controller breaks the moment the file is minified.

Output:

Build a Basic Controller in AngularJS

Because tutorialName was assigned the value “AngularJS”, that value appears in the text box and in the plain text line. A single property is enough for a demonstration; real controllers usually expose behaviour as well, which the next section covers.

How to Define Methods in AngularJS Controllers

Normally one would define multiple methods in a controller to separate the business logic. If the controller had to add two numbers and subtract two numbers, you would create one method for each operation.

The example below defines a custom method inside an AngularJS controller that returns a string.

Define Methods in AngularJS Controllers

<!-- The head and library references are unchanged from Step 3 -->
<div ng-app="DemoApp" ng-controller="DemoController">
Tutorial Name : <input type="text" ng-model="tutorialName"><br>
This tutorial is {{tName()}}
</div>

<script>
var app = angular.module('DemoApp', []);

app.controller('DemoController', ['$scope', function($scope) {
  $scope.tutorialName = "AngularJS";

  // A method on the scope, callable from the view as tName()
  $scope.tName = function() {
    return $scope.tutorialName;
  };
}]);
</script>

Code Explanation:

  1. A function is attached to the scope object as the member tName. It returns the current value of tutorialName.
  2. The view calls the method with {{tName()}}. The parentheses matter: without them the expression prints the function itself rather than its result.

โš ๏ธ Correction: the original method read $scope.tName = function() { return $scope.tName; };. That function returns itself, not the tutorial name, so the page rendered a function body instead of text. It now returns $scope.tutorialName.

Output:

Define Methods in AngularJS Controllers

So far everything has lived in one file. Production applications keep controllers separate, which is what the next section demonstrates.

AngularJS Controller with ng-Controller Example

The “HelloWorld” example above placed all functionality in a single file. It is now time to move the controller code into its own file.

Step 1) In the app.js file, add the following code for your controller.

AngularJS Controller with ng-Controller

angular.module('app', [])
  .controller('HelloWorldCtrl', ['$scope', function($scope) {
    $scope.message = "Hello World";
  }]);

The above code does the following:

  1. Defines a module called “app” which holds the controller.
  2. Creates a controller named “HelloWorldCtrl” that displays a “Hello World” message.
  3. Uses the scope object to pass information from the controller to the view, in this case a variable called message.

Step 2) In Sample.html, add a div carrying the ng-controller directive and a reference to the member variable message. Remember to reference app.js, which holds the controller source.

AngularJS Controller with ng-Controller

<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="UTF-8">
<title>Event Registration</title>
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body>
<h1> Guru99 Global Event</h1>
<div class="container">
<div ng-controller="HelloWorldCtrl">{{message}}</div>
</div>

<script src="lib/angular.js"></script>
<script src="app.js"></script>
</body>
</html>

โš ๏ธ Correction: app.js must be loaded after angular.js, since it calls angular.module. The original also loaded the library twice and carried the same chrset typo.

Output:

AngularJS Controller with ng-Controller

Every example so far has read and written properties directly on $scope. The section below covers the alternative that the AngularJS team recommends instead.

How to Use the controllerAs Syntax in AngularJS

Binding directly to $scope works, but it becomes ambiguous as soon as controllers are nested. A view expression such as {{name}} gives no clue which controller owns name, and because child scopes inherit from parent scopes prototypally, a nested controller that writes to an inherited primitive silently creates its own shadow copy. The controllerAs syntax removes both problems by giving each controller an alias.

Step 1) Alias the controller in the view using the as keyword, then prefix every binding with that alias.

Step 2) Inside the controller, attach properties to this rather than to $scope.

<div ng-controller="DemoController as demo">
Tutorial Name : <input type="text" ng-model="demo.tutorialName">
This tutorial is {{demo.tutorialName}}
</div>

<script>
app.controller('DemoController', function() {
  // 'vm' is captured so nested functions keep the right reference
  var vm = this;
  vm.tutorialName = "AngularJS";

  vm.tName = function() {
    return vm.tutorialName;
  };
});
</script>

Three gains follow. Bindings become self-documenting, because demo.tutorialName names its owner. Nested controllers stop colliding, since a parent aliased outer and a child aliased inner can both expose name. Values also bind through an object rather than a bare primitive, sidestepping the trap where an edit in a child never reaches the parent.

๐Ÿ’ก Tip: Capture this into a variable such as vm at the top of the controller. Inside a callback, this refers to something else entirely, and the captured reference keeps the binding correct.

Choosing a binding style is one decision. Deciding what belongs in a controller at all is another, and the comparison below draws that line.

Controller vs Service in AngularJS

Beginners frequently overload the controller with work that belongs in a service. The distinction is lifespan and reuse: a controller exists only while its view is on screen, whereas a service is a singleton that lives for the life of the application.

Aspect Controller Service
Lifetime Created and destroyed with the view Single instance for the whole application
Purpose Prepare data for one view Shared logic, state and server calls
Reusable No, tied to its view Yes, injectable anywhere
Holds state between views No, state is lost on navigation Yes, state persists
Typical content Scope properties and view methods HTTP calls, caching, business rules

Keep controllers thin. If two controllers need the same logic, or if a value must survive navigation between views, move it into a service and inject that service where it is needed. A practical test is to ask whether the code would still make sense with the current screen closed. If the answer is yes, it belongs in a service.

FAQs

Yes. AngularJS creates a separate instance and a separate scope for every element carrying the directive. The instances share no state, so a change in one does not appear in the other.

Declare it in the route when the controller belongs to a whole view loaded by routing. Use ng-controller for a component that appears inside a page regardless of the current route. Never declare both, or the controller runs twice.

Use the array annotation, listing dependency names as strings before the function. Minifiers rename function arguments but never string literals, so the injector still resolves $scope and any services correctly.

Yes. AI assistants produce the module, controller and scope bindings from a plain description of the screen. Always check the dependency annotation, since generated code often omits it.

AI tools rewrite scope assignments as properties on a captured vm variable and prefix every matching view binding with the alias. Review $watch calls and event listeners by hand, because those still require the scope object.

Summarize this post with: