Legacy AngularJS still appears in maintenance codebases—this sheet covers modules, directives, services, and digest-cycle pitfalls in one place. Because there is no standalone AngularJS roadmap, use the roadmaps hub to pick a modern full-stack path after you finish triage work.

Technology roadmaps hub — Explore every published roadmap; AngularJS sits alongside related web stacks here.

Getting Started

Setup AngularJS

<!-- AngularJS via CDN -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>

<!-- For development (includes debugging tools) -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.js"></script>
Note: AngularJS 1.x is different from Angular (2+). This cheatsheet covers AngularJS 1.x.

Basic Template

<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AngularJS App</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<div ng-controller="MyController">
<h1>Hello, {{name}}!</h1>
<input type="text" ng-model="name">
</div>

<script>
var app = angular.module('myApp', []);
app.controller('MyController', function($scope) {
$scope.name = 'AngularJS';
});
</script>
</body>
</html>

Directives

Core Directives

<!-- ng-app: Defines the AngularJS application -->
<div ng-app="myApp">...</div>

<!-- ng-model: Binds form elements to model data -->
<input type="text" ng-model="username">

<!-- ng-bind: Binds innerHTML to model data -->
<p ng-bind="username"></p>

<!-- ng-controller: Defines a controller -->
<div ng-controller="MyController">...</div>

<!-- ng-repeat: Repeats HTML for each item in a collection -->
<li ng-repeat="item in items">{{item.name}}</li>

<!-- ng-show/ng-hide: Shows/hides elements -->
<div ng-show="isVisible">Visible content</div>
<div ng-hide="isHidden">Hidden content</div>

<!-- ng-if: Conditionally includes HTML -->
<div ng-if="user.loggedIn">Welcome back!</div>

<!-- ng-class: Dynamically sets CSS classes -->
<div ng-class="{active: isActive, 'text-muted': isDisabled}">...</div>

<!-- ng-style: Sets CSS styles -->
<div ng-style="{color: myColor, 'font-size': fontSize + 'px'}">...</div>

Event Directives

<!-- ng-click: Handles click events -->
<button ng-click="count = count + 1">Increment</button>
<button ng-click="submitForm()">Submit</button>

<!-- ng-dblclick: Handles double click events -->
<div ng-dblclick="editItem(item)">Double click to edit</div>

<!-- ng-change: Handles change events -->
<input type="text" ng-model="username" ng-change="checkUsername()">

<!-- ng-blur: Handles blur events -->
<input type="email" ng-model="email" ng-blur="validateEmail()">

<!-- ng-focus: Handles focus events -->
<input type="text" ng-model="search" ng-focus="showSuggestions()">

<!-- ng-keyup, ng-keydown, ng-keypress -->
<input type="text" ng-keyup="checkEnter($event)">

<!-- ng-mouseenter, ng-mouseleave -->
<div ng-mouseenter="showTooltip()" ng-mouseleave="hideTooltip()">Hover me</div>

<!-- ng-submit: Handles form submission -->
<form ng-submit="processForm()">
<input type="text" ng-model="data">
<button type="submit">Submit</button>
</form>

Expressions & Filters

Expressions

<!-- Basic expressions -->
<p>Hello, {{user.name}}!</p>
<p>Total: {{quantity * price}}</p>
<p>Status: {{isActive ? 'Active' : 'Inactive'}}</p>

<!-- Using functions in expressions -->
<p>Welcome, {{getFullName()}}</p>
<p>Next year: {{currentYear + 1}}</p>

<!-- Object access -->
<p>City: {{user.address.city}}</p>
<p>Zip: {{user['address']['zip']}}</p>

<!-- Array access -->
<p>First item: {{items[0]}}</p>
<p>Array length: {{items.length}}</p>

<!-- One-time binding (AngularJS 1.3+) -->
<p>Initial value: {{::initialValue}}</p>

<!-- ng-bind for one-time binding -->
<span ng-bind="::user.name"></span>

Filters

<!-- Built-in filters -->
<p>{{ price | currency }}</p>
<p>{{ date | date:'medium' }}</p>
<p>{{ message | uppercase }}</p>
<p>{{ text | limitTo:100 }}</p>
<p>{{ object | json }}</p>
<p>{{ items | filter:searchText }}</p>
<p>{{ items | orderBy:'name' }}</p>

<!-- Chaining filters -->
<p>{{ date | date:'fullDate' | uppercase }}</p>
<p>{{ items | filter:searchText | orderBy:'name' }}</p>

<!-- Using filters in JavaScript -->
<script>
app.controller('MyCtrl', function($scope, $filter) {
$scope.formattedDate = $filter('date')($scope.rawDate, 'yyyy-MM-dd');
$scope.upperText = $filter('uppercase')($scope.text);
});
</script>

<!-- Creating custom filters -->
<script>
app.filter('reverse', function() {
return function(input) {
return input.split('').reverse().join('');
};
});
</script>
<p>{{ 'hello' | reverse }}</p> <!-- Displays 'olleh' -->

Controllers & Scope

Controllers

<!-- Basic controller -->
<script>
var app = angular.module('myApp', []);

app.controller('MyController', function($scope) {
$scope.message = 'Hello World!';
$scope.user = { name: 'John', age: 30 };

$scope.sayHello = function() {
alert('Hello ' + $scope.user.name);
};
});
</script>

<!-- Controller with dependencies -->
<script>
app.controller('UserController', ['$scope', '$http', '$location',
function($scope, $http, $location) {
$scope.loadUser = function() {
$http.get('/api/user').then(function(response) {
$scope.user = response.data;
});
};

$scope.redirect = function(path) {
$location.path(path);
};
}]);
</script>

<!-- Controller As syntax -->
<script>
app.controller('MyController', function() {
this.message = 'Hello World!';
this.sayHello = function() {
alert(this.message);
};
});
</script>
<div ng-controller="MyController as ctrl">
<p>{{ctrl.message}}</p>
<button ng-click="ctrl.sayHello()">Say Hello</button>
</div>

Scope

<!-- $scope properties and methods -->
<script>
app.controller('MyController', function($scope) {
// Primitive values
$scope.title = 'My App';
$scope.count = 0;

// Objects
$scope.user = {
name: 'John Doe',
email: 'john@example.com'
};

// Arrays
$scope.items = ['Item 1', 'Item 2', 'Item 3'];

// Functions
$scope.increment = function() {
$scope.count++;
};

$scope.addItem = function(item) {
$scope.items.push(item);
};

// $watch for changes
$scope.$watch('count', function(newVal, oldVal) {
console.log('Count changed from ' + oldVal + ' to ' + newVal);
});

// $watch for object changes
$scope.$watch('user', function(newVal, oldVal) {
console.log('User changed');
}, true); // deep watch
});
</script>

<!-- Scope inheritance example -->
<div ng-controller="ParentController">
Parent: {{parentValue}}
<div ng-controller="ChildController">
Child: {{parentValue}} <!-- Inherits from parent -->
Child: {{childValue}}
</div>
</div>

Services

Built-in Services

<!-- $http service for AJAX requests -->
<script>
app.controller('MyController', function($scope, $http) {
// GET request
$http.get('/api/users')
.then(function(response) {
$scope.users = response.data;
})
.catch(function(error) {
console.error('Error:', error);
});

// POST request
$http.post('/api/users', { name: 'John', age: 30 })
.then(function(response) {
console.log('User created:', response.data);
});

// With configuration
$http({
method: 'GET',
url: '/api/users',
params: { limit: 10, offset: 20 },
headers: { 'Authorization': 'Bearer token123' }
}).then(function(response) {
$scope.users = response.data;
});
});
</script>

<!-- $timeout and $interval -->
<script>
app.controller('MyController', function($scope, $timeout, $interval) {
// $timeout - single delay
$timeout(function() {
$scope.message = 'This appears after 2 seconds';
}, 2000);

// $interval - repeated execution
var counter = 0;
var stop = $interval(function() {
counter++;
$scope.counter = counter;
if (counter >= 10) {
$interval.cancel(stop);
}
}, 1000);
});
</script>

<!-- $location service -->
<script>
app.controller('MyController', function($scope, $location) {
// Get current path
$scope.currentPath = $location.path();

// Change location
$scope.goTo = function(path) {
$location.path(path);
};

// Get search parameters
$scope.searchParams = $location.search();
});
</script>

Custom Services

<!-- Creating a service with .service() -->
<script>
app.service('UserService', function() {
this.users = [];

this.addUser = function(user) {
this.users.push(user);
};

this.getUsers = function() {
return this.users;
};

this.clearUsers = function() {
this.users = [];
};
});
</script>

<!-- Creating a service with .factory() -->
<script>
app.factory('DataService', function() {
var data = {};

var service = {
set: function(key, value) {
data[key] = value;
},
get: function(key) {
return data[key];
},
getAll: function() {
return data;
}
};

return service;
});
</script>

<!-- Creating a value service -->
<script>
app.value('apiKey', 'abc123def456ghi789');
app.value('appConfig', {
version: '1.0.0',
environment: 'development',
apiUrl: 'https://api.example.com'
});
</script>

<!-- Creating a constant service -->
<script>
app.constant('APP_NAME', 'My AngularJS App');
app.constant('MAX_FILE_SIZE', 10485760); // 10MB
</script>

<!-- Using custom services in controllers -->
<script>
app.controller('MyController', function($scope, UserService, DataService, apiKey, appConfig) {
$scope.apiKey = apiKey;
$scope.config = appConfig;

$scope.addUser = function(user) {
UserService.addUser(user);
};

$scope.getUsers = function() {
return UserService.getUsers();
};

$scope.saveData = function(key, value) {
DataService.set(key, value);
};

$scope.loadData = function(key) {
return DataService.get(key);
};
});
</script>

Routing

Basic Routing

<!-- Include ngRoute module -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular-route.min.js"></script>

<!-- Set up the app to use ngRoute -->
<script>
var app = angular.module('myApp', ['ngRoute']);

app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/home.html',
controller: 'HomeController'
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutController'
})
.when('/contact', {
templateUrl: 'views/contact.html',
controller: 'ContactController'
})
.when('/user/:id', {
templateUrl: 'views/user.html',
controller: 'UserController'
})
.otherwise({
redirectTo: '/'
});
});
</script>

<!-- Add ng-view directive to your HTML -->
<div ng-view></div>

<!-- Navigation links with href -->
<a href="#/">Home</a>
<a href="#/about">About</a>
<a href="#/contact">Contact</a>
<a href="#/user/123">User Profile</a>

<!-- Navigation with ng-href -->
<a ng-href="#/user/{{userId}}">My Profile</a>

Advanced Routing

<!-- Route with resolve -->
<script>
app.config(function($routeProvider) {
$routeProvider
.when('/dashboard', {
templateUrl: 'views/dashboard.html',
controller: 'DashboardController',
resolve: {
userData: function(UserService) {
return UserService.getUser();
},
appSettings: function(ConfigService) {
return ConfigService.loadSettings();
}
}
});
});

// Controller using resolved data
app.controller('DashboardController', function($scope, userData, appSettings) {
$scope.user = userData;
$scope.settings = appSettings;
});
</script>

<!-- Using $routeParams -->
<script>
app.controller('UserController', function($scope, $routeParams) {
$scope.userId = $routeParams.id;

// Load user based on ID
$scope.loadUser = function() {
UserService.getUser($scope.userId).then(function(user) {
$scope.user = user;
});
};
});
</script>

<!-- Using $route service -->
<script>
app.controller('NavController', function($scope, $route) {
// Watch for route changes
$scope.$on('$routeChangeSuccess', function(event, current, previous) {
$scope.currentRoute = current.originalPath;
});

// Check if a route is active
$scope.isActive = function(route) {
return $route.current && $route.current.originalPath === route;
};
});
</script>

<!-- HTML with active route highlighting -->
<nav>
<a href="#/" ng-class="{active: isActive('/')}">Home</a>
<a href="#/about" ng-class="{active: isActive('/about')}">About</a>
<a href="#/contact" ng-class="{active: isActive('/contact')}">Contact</a>
</nav>

Form Validation

Form Basics

<!-- Basic form with validation -->
<form name="userForm" ng-submit="submitForm()" novalidate>

<div class="form-group">
<label>Name:</label>
<input type="text" name="userName" ng-model="user.name" required class="form-control">
<span ng-show="userForm.userName.$error.required && userForm.userName.$touched" class="text-danger">
Name is required.
</span>
</div>

<div class="form-group">
<label>Email:</label>
<input type="email" name="userEmail" ng-model="user.email" required class="form-control">
<span ng-show="userForm.userEmail.$error.required && userForm.userEmail.$touched" class="text-danger">
Email is required.
</span>
<span ng-show="userForm.userEmail.$error.email && userForm.userEmail.$touched" class="text-danger">
Please enter a valid email.
</span>
</div>

<button type="submit" ng-disabled="userForm.$invalid" class="btn btn-primary">
Submit
</button>

</form>

<!-- Display form validation states -->
<div>
Form valid: {{userForm.$valid}}<br>
Form invalid: {{userForm.$invalid}}<br>
Form submitted: {{userForm.$submitted}}<br>
Form pristine: {{userForm.$pristine}}<br>
Form dirty: {{userForm.$dirty}}<br>
</div>

Advanced Validation

<!-- Custom validation with ng-pattern -->
<div class="form-group">
<label>Username:</label>
<input type="text" name="username" ng-model="user.username" ng-pattern="/^[a-zA-Z0-9_]{3,20}$/" required class="form-control">
<span ng-show="userForm.username.$error.pattern" class="text-danger">
Username must be 3-20 characters and can only contain letters, numbers, and underscores.
</span>
</div>

<!-- Custom validation with directive -->
<script>
app.directive('validatePassword', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$validators.password = function(modelValue, viewValue) {
var value = modelValue || viewValue;
// At least 8 chars, one uppercase, one lowercase, one number
return /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/.test(value);
};
}
};
});
</script>

<div class="form-group">
<label>Password:</label>
<input type="password" name="password" ng-model="user.password" validate-password required class="form-control">
<span ng-show="userForm.password.$error.password" class="text-danger">
Password must be at least 8 characters and contain at least one uppercase letter, one lowercase letter, and one number.
</span>
</div>

<!-- Matching password confirmation -->
<div class="form-group">
<label>Confirm Password:</label>
<input type="password" name="confirmPassword" ng-model="user.confirmPassword" compare-to="user.password" required class="form-control">
<span ng-show="userForm.confirmPassword.$error.compareTo" class="text-danger">
Passwords do not match.
</span>
</div>

<!-- Custom compare-to directive -->
<script>
app.directive('compareTo', function() {
return {
require: 'ngModel',
scope: {
otherModelValue: '=compareTo'
},
link: function(scope, element, attributes, ngModel) {
ngModel.$validators.compareTo = function(modelValue) {
return modelValue == scope.otherModelValue;
};

scope.$watch('otherModelValue', function() {
ngModel.$validate();
});
}
};
});
</script>

Best Practices

Performance

// 1. Limit watchers
// Use one-time binding (::) where possible
<h1>{{::pageTitle}}</h1>
<span ng-bind="::user.name"></span>

// 2. Use track by in ng-repeat
<li ng-repeat="item in items track by item.id">
{{item.name}}
</li>

// 3. Debounce ng-model updates
<input type="text" ng-model="searchQuery" ng-model-options="{ debounce: 300 }">

// 4. Avoid expensive operations in templates
// Instead of:
<div>{{ calculateTotal() }}</div>

// Prefer:
<script>
$scope.$watch('items', function(newItems) {
$scope.total = calculateTotal(newItems);
}, true);
</script>
<div>{{total}}</div>

// 5. Use $applyAsync and $digest
<script>
// Instead of $apply, use $applyAsync when possible
$scope.$applyAsync(function() {
$scope.data = newData;
});

// Or use $timeout for safe apply
$timeout(function() {
// Code that might need a digest cycle
});
</script>

Code Organization

// 1. Use Controller As syntax
<div ng-controller="UserController as userCtrl">
<h1>{{userCtrl.title}}</h1>
<button ng-click="userCtrl.save()">Save</button>
</div>

app.controller('UserController', function() {
this.title = 'User Profile';
this.save = function() {
// Save logic
};
});

// 2. Use modules to organize code
// app.js
angular.module('myApp', ['myApp.controllers', 'myApp.services', 'myApp.directives']);

// controllers.js
angular.module('myApp.controllers', [])
.controller('MainController', function() {})
.controller('UserController', function() {});

// services.js
angular.module('myApp.services', [])
.service('UserService', function() {})
.factory('DataService', function() {});

// 3. Use dependency injection array syntax
app.controller('MyController', ['$scope', '$http', 'UserService',
function($scope, $http, UserService) {
// Controller logic
}]);

// 4. Use constants for configuration
app.constant('APP_CONFIG', {
apiUrl: 'https://api.example.com',
version: '1.0.0',
debug: true
});

// 5. Use services for business logic
app.service('UserService', function() {
this.getUser = function(id) {
// API call logic
};

this.saveUser = function(user) {
// Save logic
};
});

Quick Reference

Common Patterns

// 1. Toggle functionality
<button ng-click="isVisible = !isVisible">Toggle</button>
<div ng-show="isVisible">Content</div>

// 2. Load data on controller initialization
app.controller('MyController', function($scope, DataService) {
$scope.items = [];

$scope.loadData = function() {
DataService.getItems().then(function(response) {
$scope.items = response.data;
});
};

// Load data immediately
$scope.loadData();
});

// 3. Form reset
$scope.resetForm = function() {
$scope.user = {};
$scope.userForm.$setPristine();
$scope.userForm.$setUntouched();
};

// 4. Filter and search
<input type="text" ng-model="searchText" placeholder="Search...">
<div ng-repeat="item in items | filter:searchText">
{{item.name}}
</div>

// 5. Pagination
$scope.currentPage = 1;
$scope.itemsPerPage = 10;

$scope.paginatedItems = function() {
var start = ($scope.currentPage - 1) * $scope.itemsPerPage;
var end = start + $scope.itemsPerPage;
return $scope.items.slice(start, end);
};

$scope.totalPages = Math.ceil($scope.items.length / $scope.itemsPerPage);

Common Pitfalls

// 1. Dot rule in ng-model
// Avoid:
<input type="text" ng-model="username">
// This creates a child scope property, not on the parent scope

// Prefer:
<input type="text" ng-model="user.username">
// This ensures proper scope inheritance

// 2. ng-if creates a child scope
<div ng-if="condition">
<input type="text" ng-model="value">
<!-- This creates a child scope property -->
</div>

// 3. Using $index in ng-repeat with dynamic lists
// Avoid using $index as a unique identifier
<div ng-repeat="item in items">
<input type="text" ng-model="item.name">
<button ng-click="removeItem($index)">Remove</button>
<!-- $index changes when items are filtered or sorted -->
</div>

// Prefer using track by with a unique identifier
<div ng-repeat="item in items track by item.id">
<input type="text" ng-model="item.name">
<button ng-click="removeItem(item.id)">Remove</button>
</div>

// 4. Memory leaks with $watch and $on
// Always deregister watchers and listeners
var deregister = $scope.$watch('value', function(newVal) {
// Watch logic
});

// Deregister when no longer needed
$scope.$on('$destroy', function() {
deregister();
});

// 5. Digest already in progress errors
// Use $timeout instead of $apply when unsure
$http.get('/api/data').then(function(response) {
$timeout(function() {
$scope.data = response.data;
});
});
Quick reference guide

Comprehensive AngularJS Frontend Cheatsheet Reference

This AngularJS Frontend cheatsheet on Nikhil Learn Hub collects syntax, commands, and practical snippets for quick revision. Explore AngularJS directives, controllers, services, data binding, and frontend concepts with easy examples.

Use the reference cards and examples above during coding sessions; return here instead of scattered searches when you need dependable reminders. Follow the Technology roadmaps hub when you want structured lessons beyond one-page lookups.

Quick lookup coverage

  • Syntax, commands, and API signatures
  • Copy-ready examples and common patterns
  • Terminology for coursework and interviews
  • Cross-links to the matching learning roadmap

How to study with this sheet

  • Production debugging and tuning reminders
  • Security, performance, or scale cautions
  • Integration with adjacent stacks on this site
  • Deeper study through tutorials and roadmaps

Who Should Use This Cheatsheet

Students, self-taught developers, and professionals who need fast AngularJS Frontend lookups during labs, debugging, or interview revision should keep this page bookmarked.