Click here to Skip to main content
15,885,546 members
Articles / Web Development / ASP.NET
Tip/Trick

AngularJS ng-repeat Alternative Approach

Rate me:
Please Sign up or sign in to vote.
3.08/5 (6 votes)
11 Jul 2016CPOL3 min read 46.8K   3   7
How to replace the ng-repeat with Custom Directive

Introduction

This is about alternative approach to ng-repeat to handle heavy data binding with better page performance. This article will provide insights of how to replace particular ng-repeat with particular data.

When to Avoid ng-repeat

ng-repeat is good, if the data is less. But if heavy data is to be displayed from a collection, it is good to have the Custom Directive approach.

Especially if the data is going to be static/read only, definitely the ng-repeat should be avoided.

Expressions in ng-repeat & $watch

Each expression will create a $watch in Angular.

To handle 2 way binding, Angular will keep on watching all the scope values continuously. In other words, whenever one of the $scope values is changed, it will check all the $watches in the application.

In this ng-repeat, if the row contains 15 columns with binding expression. If the data rows are 1000+, then $watch will become 15000. So performance is affecting primarily.

Alternative to ng-repeat for single instance

If the content is to be static, if we don't require 2 way binding, need to go for one time binding syntax. {{::value}}

If the angularJS version of the application is below 1.3, the one time binding syntax will not support. Best alternative approach is Custom Directive. In other words, the static data could be formed with Angular features with simple steps as mentioned below.

Implementation

Here, we will create Unordered List and will bind the contents as List Contents of Students data dynamically.

As a first step, just create UL tag only as container.

Where List Contents will be displayed?

We will render the List contents(<LI>) dynamically. Place a DIV and provide the unique attribute name "repeater-alternative-forstudentdata"- which will be used in rendering flow.

HTML
<div>
    <ul>
        <div repeater-alternative-forstudentdata></div>
    </ul>
</div>

What is the source for that List?

Assign collection data to be displayed in the Angular's $scope.

JavaScript
// Assuming heavy value is retrieved from the server. Here only sample values are given
var studentsList = 
[
    {
       FirstName: "Raj,
       LastName : "B",
       Country : "India",
       BirthDate: "01/01/1990"
    },
    {
       FirstName: "Kumar,
       LastName : "S",
       Country : "India",
       BirthDate: "01/01/1990"
    },
    ..................
  ..................
  ..................
  ..................
];

$scope.collectionObject = studentsList; //Assign to Angular $scope for processing.

Where is the actual List Content?

Our aim is to repeat the collection object and will display the list. So form the similar logic - loop the collection and form the string as we desire to display.

JavaScript
var tableRow = "";
angular.forEach($scope.collectionObject, function (item) {
    tableRow = tableRow + ['<li>',
    '<div class="col-md-1">' + item.FirstName + '</div> ',
    '<div class="col-md-1 ">' + item.LastName + '</div> ',
    '<div class="col-md-1 ">' + item.Country+ '</div> ',
    '<div class="col-md-1 ">' + item.Id + '</div> ',
    '<div class="col-md-1 ">' + 
    $filter('date')(item.BirthDate, 'dd-MMM-yyyy') + '</div> ',
    '</li>'].join('');
});

But Where to Place this List Forming logic?

Once the value of collectionObject is available(assigned), we need to form prepare the table and need to display.

But How Do We Know - WHEN the value is assigned/available to the CollectionObject?

Angular is watching all the $scope variable changes. whenever its value is changed, it is listener -$watch is fired. So we will place the logic in that's $scope variable's $watch.

For this scope variable, whenever its value is changed, it is firing the following function:

JavaScript
$scope.$watch($scope.object, function (oldValue, newValue) { 
})

So we will place the logic in that $scope variable's $watch. In other words, when we assign the value, Angular processes the value and forms the List Content.

JavaScript
$scope.$watch('collectionObject', function (oldValue, newValue) {
    var tableRow = "";
    angular.forEach($scope.collectionObject, function (item) {
        tableRow = tableRow + ['<li>',
        '<div class="col-md-1">' + item.FirstName + '</div> ',
        '<div class="col-md-1 ">' + item.LastName + '</div> ',
        '<div class="col-md-1 ">' + item.State + '</div> ',
        '<div class="col-md-1 ">' + item.Id + '</div> ',
        '<div class="col-md-1 ">' + 
        $filter('date')(item.BirthDate, 'dd-MMM-yyyy') + '</div> ',
        '</li>'].join('');
    });
})

But how will the Angular render this table under that HTML <div>.

repeater-alternative-forstudentdata ?

With the help of Angualr's Directive concepts, we achieve.
In brief, we instruct the Angular -
When the particular named element is found,
What to do as Post Processing Operation
JavaScript
var userDirectives = angular.module([]);

userDirectives.directive('DOMElementFound', function () {
    return {
        replace: true,
        link: function ($scope, $elem, attrs) {
                  //Post processing operations
        }
    }
});

In this example, we inform Angular when the "repeater-alternative-forstudentdata" element is found, append these list rows(divs).

The syntax of the Angular directive is as follows:

JavaScript
var userDirectives = angular.module([]);

userDirectives.directive('repeaterAlternativeForstudentdata', function () {
    return {
        replace : true,
        link: function ($scope, $elem, attrs) {

            $scope.$watch('collectionObject', function (oldValue, newValue) {
                var tableRow = "";
                angular.forEach($scope.collectionObject, function (item) {
                    tableRow = tableRow + ['<li>',
                                    '<div class="col-md-1">' + item.FirstName + '</div> ',
                                    '<div class="col-md-1 ">' + item.LastName + '</div> ',
                                    '<div class="col-md-1 ">' + item.State + '</div> ',
                                    '<div class="col-md-1 ">' + item.Id + '</div> ',
                                    '<div class="col-md-1 ">' + $filter('date')
                                     (item.BirthDate, 'dd-MMM-yyyy') + '</div> ',
                                    '</li>'].join('');
                });

                
                //If IE is your primary browser, 
                //innerHTML is recommended to increase the performance
                $elem.context.innerHTML = tableRow;
                //If IE is not your primary browser, 
                //just appending the content to the element is enough .
                //$elem.append(tableRow);
            });
        }
    }
});

Output

In brief, we simulate ng-repeat, but with static content for particular data. So output will be similar to ng-repeat, but will render faster, since there is no 2 way binding - no 'n' number of $watchers.

Notes

The aim of the article is how to replace ng-repeat with Custom Directive for particular data. So Directive is just brief. More details on Directive will be in future articles.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
India India
Full time Coder.

Comments and Discussions

 
QuestionHow can i add onclick or ng click Pin
PRASAD GDV28-Oct-19 10:20
PRASAD GDV28-Oct-19 10:20 
QuestionIt is not alternative of ng-repeat. Pin
Sanjay K. Gupta15-Jun-16 18:56
professionalSanjay K. Gupta15-Jun-16 18:56 
AnswerRe: It is not alternative of ng-repeat. Pin
Karthik Coder16-Jun-16 6:03
professionalKarthik Coder16-Jun-16 6:03 
QuestionI must be missing something... Pin
Michael Gledhill10-Jun-16 3:35
Michael Gledhill10-Jun-16 3:35 
AnswerRe: I must be missing something... Pin
Karthik Coder14-Jun-16 5:54
professionalKarthik Coder14-Jun-16 5:54 
Bug[My vote of 1] OneWay vs OneTime Pin
davrot24-May-16 21:20
davrot24-May-16 21:20 
GeneralRe: [My vote of 1] OneWay vs OneTime Pin
Karthik Coder25-May-16 1:45
professionalKarthik Coder25-May-16 1:45 
Thanks. I updated. One time binding will not track, But One way binding will track.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.