• David Tessaro

ng-repeat: Demystifying AngularJS and Service Portal

The Demystifying AngularJS and Service Portal is a series for anyone interested in taking short, deep dives into the world of AngularJS in Service Portal, and most ideal for those with little or no experience.


In this post, we’ll explore the AngularJS directive ng-repeat. A directive is a bit of functionality that can easily be included in our portal widgets. The ng-repeat directive is the way we loop HTML elements in tons of widgets like header dropdown menu items, catalog item buttons, a list of a user’s incidents, and much more.

To illustrate how it works, let’s consider a list of Catalog Items:

  1. Laptop

  2. Monitor

  3. Smart Phone

  4. Tablet

  5. Password Reset

  6. Email Distribution Group

Before Service Portal, we used JellyScript and HTML on CMS pages to render a list like the one above. Mmmm, remember jelly?

<j:while test=”${Items.next()}>

Now, with AngularJS and Service Portal, we use ng-repeat in a widget’s HTML template:

<li ng-repeat=”item in c.Items”>{{item.name}}</li>

Let’s dissect this template.

<li></li> HTML tags for a list element. This is the element that will be repeated for each entry in the data collection.

ng-repeat=”” An HTML attribute that tells the page to include the ng-repeat AngularJS directive.

item in c.Items c.Items is the name of our data collection array. item is a name we made up to identify the current entry of the data collection.

{{item.name}} item, as mentioned above, is the name of the current data collection entry. name is a property of the current item. In this case, it’s the name of the property that stores the value of the catalog item’s Name field. {{ }} is the way we insert any data provided by the widget’s client controller. In this case, we are inserting the value of the current item’s name property. In JellyScript, we used ${ }.

So what’s the big deal?

What makes ng-repeat so much greater than what we did with JellyScript?

1. We write less code

To be fair, in our example we only saved 14 characters. But a penny saved is a penny earned, and it’s a much cleaner snippet to read. However, I have seen plenty of more complex examples where ng-repeat significantly reduced the amount and complexity of the code.

2. We can sort and filter the collection right from the HTML

There are many options for manipulating the output of ng-repeat, but I’m going to focus on two: orderBy and filter.


Consider the template for our example list of Catalog Items. If we wanted to sort the collection alphabetically by the item’s name property, then we can add | orderBy: ‘+name’ to the ng-repeat attribute.

<li ng-repeat=”item in Items | orderBy:+name’>{{item.name}}</li>

For reverse sort, use  rather than +.

<li ng-repeat=”item in Items | orderBy: -name’>{{item.name}}</li>

Want to sort by name, and then by order?

<li ng-repeat=”item in Items | orderBy: [+name’,+order’]>{{item.name}}</li>


Say we wanted to filter the list by specific categories, then we can include | filter: {category: ‘Hardware’} in the ng-repeat attribute:

<li ng-repeat=”item in Items | orderBy: [+name’,+order’] | filter: {category: ‘Hardware’}>{{item.name}}</li>

Filtering without sorting would look like this.

<li ng-repeat=”item in Items | filter: {category: ‘Hardware’}>{{item.name}}</li>

We can get more advanced with these. For example, we could use variables rather than hard coding strings into the template.

<li ng-repeat=”item in Items | filter: c.category>{{item.name}}</li>

The widget controller script would return the value of c.category like this.

var c = this;
c.category = 'Hardware';

We can get even more advanced and filter by a function…

<li ng-repeat=”item in Items | filter: c.filterMyShtuff>{{item.name}}</li>

In this case, the widget controller will have a function like this.

var c = this;
c.filterMyShtuff = function() {
     var shtuff = false;
     if(everything peachy) {
          shtuff = true;
     return shtuff;

<li ng-repeat=”item in Items | filter: {category: 'Hardware'} as hardwareItems>{{item.name}}</li>

Notice how I added “as hardwareItems” to the end? Now I can use that variable to reference this filtered list. Like this:

This filtered list has {{hardwareItems.length}} items in it.

3. The HTML template can update whenever the data collection is updated

With JellyScript and CMS, once you render your list, that is it. Your list is not going to update if your data collection updates. Therefore, perhaps one of the most awesome things about the ng-repeat directive is that the template updates when the data collection updates.

To illustrate this point, consider what it takes to render our collection of catalog items.

The data collection “Items” could be defined in the widget controller.

var c = this;
this.Items = [
     {name: “Laptop”, category: “Hardware”},
     {name: “Password Reset”, category: “Applications”}

The HTML template looks like this.

<li ng-repeat=”item in c.Items”>{{item.name}}</li>

The result is a list like this.

  1. Laptop

  2. Password Reset

Now, If you were to change the c.Items array to include a new object…

this.Items = [
     {name: “Laptop”, category: “Hardware”},
 {name: “Email Distribution Group”, category: “Email”},
     {name: “Password Reset”, category: “Applications”}

Then, the result is automatically updated, and the user now sees the new item in the output without having to refresh the page.

  1. Laptop

  2. Email Distribution Group

  3. Password Reset

Or, if only a part of the data collection changes, such as the name property…

this.Items = [
     {name:Lenovo Laptop, category: “Hardware”},
     {name: “Email Distribution Group”, category: “Email”},
     {name: “Password Reset”, category: “Applications”}

Then the HTML element that is affected by the data change is immediately updated, with no page reloading at all:

  1. Lenovo Laptop

  2. Email Distribution Group

  3. Password Reset

What if you’re stingy and you don’t want the name to change once it’s loaded? Having this option is good, in case the thing we’re repeating has the potential of being a performance hog or causing some other issue. To stop the element from responding to data collection changes, simply include :: at the beginning of the curly braces.

<li ng-repeat=”item in c.Items”>{{::item.name}}</li>

“Gee, that’s great,” you might be thinking, “but how does my data collection update automatically when the server data changes?” The answer lies in a portal utility called spUtil.record. We’ll cover that and more, next time in Demystifying AngularJS and Service Portal! Till next time, go out and get gnarly with ng-repeat!

#customizingserviceportal #ngrepeat #serviceportal #serviceportalhowto