Filters
A filter formats a value for display without changing the underlying data — the same idea as a Unix pipe, and in fact it uses the same | symbol. AngularJS ships with a handful of filters for the formatting jobs that come up in nearly every app: currency, dates, and text case.
Using a built-in filter
A filter goes after the value it applies to, separated by |, directly inside an expression:
<div ng-app="" ng-init="price = 42.5, purchased = new Date(2026, 8, 9)"> <p>Price: {{ price | currency }}</p> <p>Purchased: {{ purchased | date:'longDate' }}</p> </div>
Price: $42.50 Purchased: September 9, 2026
currency adds the $ sign and rounds to two decimal places automatically; date:'longDate' takes an optional format-string argument, passed after a colon, telling it exactly how to render the date. Neither filter changed price or purchased themselves — only what got displayed.
Chaining filters
Filters can be stacked, each one operating on the previous filter's output:
<div ng-app="" ng-init="title = 'server error'"> <p>{{ title | uppercase | limitTo:6 }}</p> </div>
SERVER
uppercase runs first, producing "SERVER ERROR", and limitTo:6 then truncates that result to its first 6 characters — order matters, exactly like piping commands together in a terminal.
Filtering an ng-repeat list
The filter filter is a special case — used inline with ng-repeat to show only items matching some criteria, without writing any filtering logic in the controller:
<div ng-app="" ng-init="names = ['Priya', 'Sam', 'Priyanka', 'Alex'], query = 'pri'"> <li ng-repeat="n in names | filter:query">{{ n }}</li> </div>
• Priya • Priyanka
filter:query keeps only the array entries that case-insensitively contain query's current value — bind query to a text input with ng-model and this becomes a live search box with zero JavaScript filtering logic written by hand.
filter and any custom filter you write get re-run on every single digest cycle, for every item in the array — not just when the underlying data actually changes. On a list of a few dozen items this is invisible; on a list of several thousand, a filter (especially one doing real work, like a case-insensitive substring search) can become a measurable slowdown. This is the same underlying cost as the digest cycle re-checking all your bindings, just applied to filtering specifically.