var app = angular.module('twoway', ['twoway.services', 'pasvaz.bindonce']);

app.controller('MainCtrl', function($scope, $timeout, appconstant, helpers) {
    $scope.loadPersons = function(number) {
        var gender = '?';
        for (var i = 0; i < number; i++) {
            gender = helpers.randomGender();
            $scope.Persons.push({
                firstname: helpers.randomName(8),
                lastname: helpers.randomName(8),
                age: helpers.randomAge(),
                gender: gender,
                picture: appconstant.avatars[gender],
                url: helpers.randomUrl()
            });
        }
        $scope.wcount();
    };

    $scope.ageColor = function(age) {
        // Do you want to see how many dirty checking run? Uncomment next line
        // console.log('Dirty Checking running', (new Date()));
        var color = (age < 18) ? 'minor' : ((age > 60) ? 'senior' : 'average');
        return appconstant.ageColors[color];
    };

    $scope.reset = function() {
        $scope.name = "";
        $scope.Persons = [{
            firstname: 'Pasquale',
            lastname: 'Vazzana',
            age: 28,
            gender: 'M',
            picture: appconstant.avatars['M'],
            link: ''
        }];

        $scope.wcount();
    };

    $scope.wcount = function() {
        $timeout(function() {
            $scope.watchers = helpers.watchersContainedIn($scope);
        });
    };

    $scope.reset();
});
<!DOCTYPE html>
<html ng-app="twoway">

<head>
    <meta charset="utf-8" />
    <title>Twoway Databinding with BindOnce</title>
    <link data-require="bootstrap-css@3.1.1" data-semver="2.3.2" rel="stylesheet" href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" />
    <script data-require="angular.js@*" data-semver="1.1.5" src="http://code.angularjs.org/1.1.5/angular.js"></script>
    <script data-require="bindonce@0.3.1" data-semver="0.3.1" src="http://pasvaz.github.io/bindonce/javascripts/bindonce-0.3.1/bindonce.min.js"></script>
    <script>
        document.write('<base href="' + document.location + '" />');
    </script>
    <link rel="stylesheet" href="style.css" />
    <script src="app.js"></script>
    <script src="services.js"></script>
</head>

<body ng-controller="MainCtrl">
    <h3>Reactiveness Test - <span class="text-info">BindOnce version</span></h3>
    <form>
        <div class="title">{{ name || 'Press & hold a key until it fills the input to test the reactiveness' }}</div>
        <input type="text" ng-model="name" />
        <div class="controls">
            <button class="btn btn-primary" ng-click="reset()">Reset</button>
            <button class="btn btn-success" ng-click="loadPersons(500)">Load 500</button>
            <button class="btn btn-warning" ng-click="loadPersons(1000)">Load 1000</button>
            <button class="btn btn-danger" ng-click="loadPersons(2000)">Load 2000</button>
            <a target="_parent" href="http://plnkr.co/edit/jwrHVb?p=preview" style="float:right" class="btn btn-inverse">without BindOnce</a>
        </div>
    </form>
    <hr />

    <legend>
        <span ng-bind="Persons.length" class="badge badge-important"></span>
        <a>Persons</a>
        <span ng-bind="watchers" class="badge badge-important"></span>
        <a href="" ng-click="wcount()">$Watchers</a>
    </legend>
    
    <h5>This demo uses <a target="_new" href="https://github.com/Pasvaz/bindonce">BindOnce</a>, do you want to test the <a target="_parent" href="http://plnkr.co/edit/jwrHVb?p=preview">version without BindOnce</a>?</h5>

    <table class="table table-bordered">
        <tbody>

            <tr>
                <th>#</th>
                <th>Avatar</th>
                <th>First Name</th>
                <th>Last Name</th>
                <th>Age</th>
                <th>Gender</th>
                <th>Profile</th>
            </tr>

            <tr bindonce ng-repeat="person in Persons" bo-class="{'male':person.gender=='M','female':person.gender=='F'}">
                <td bo-bind="$index + 1"></td>
                <td><img bo-src="person.picture" /></td>
                <td bo-bind="person.firstname"></td>
                <td bo-bind="person.lastname"></td>
                <!-- BAD PRACTICE FOR STYLE ON PURPOSE: Using a function as binder is not good -->
                <td><span bo-bind="person.age" bo-style="ageColor(person.age)" style=""></span></td>
                <td bo-bind="person.gender"></td>
                <td>
                    <a bo-href="person.url">
                        <spam bo-bind="(person.url)?'link':'missing'" bo-class="{'label label-important':!person.url}"></spam>
                    </a>
                </td>
            </tr>

        </tbody>
    </table>
</body>

</html>
body {
    padding: 0 20px;
}
legend a {
    margin-right: 20px;
    vertical-align: middle;
}
.male {
    color: #55468C;
}
.female {
    color: #C4969E;
}
.title {
    padding: 10px 5px;
    color: red;
}
tr {
    text-align: left;
}
tr th {
    width: 20%;
}
tr td span {
    padding: 2px 10px;
}
img {
    width: 30px;
}
input {
    width: 100%;
}
var svc = angular.module('twoway.services', []);

svc.factory('helpers', function(appconstant) {

    var helpers = {

        watchersContainedIn: function(scope) {
            var watchers = (scope.$$watchers) ? scope.$$watchers.length : 0;
            var child = scope.$$childHead;
            while (child) {
                watchers += (child.$$watchers) ? child.$$watchers.length : 0;
                child = child.$$nextSibling;
            }
            return watchers;
        },

        randomGender: function() {
            return (Math.floor(Math.random() * 2) % 2 === 0) ? 'M' : 'F';
        },

        randomAge: function() {
            return Math.floor(Math.random() * 90) + 1;
        },

        randomName: function(length) {
            var nome = "";
            for (var i = 0; i < length; i++)
                nome += appconstant.letters.charAt(Math.floor(Math.random() * appconstant.letters.length));
            return nome;
        },

        randomUrl: function() {
            return (Math.floor(Math.random() * 2) % 2 === 0) ? 'http://www.' + (helpers.randomName(20) + '.' + helpers.randomName(2)).toLowerCase() : '';
        }
    }

    return helpers;
});

svc.constant('appconstant', {
    letters : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
    
    avatars: {
        'M': 'http://howlstream.com/dist/images/icons/PNG/Dude.png',
        'F': 'http://howlstream.com/dist/images/icons/PNG/Girl.png'
    },

    ageColors: {
        average: {},
        minor: {
            'background-color': 'red',
            color: 'white'
        },
        senior: {
            'background-color': 'brown',
            color: 'yellow'
        },
    }
});
##This demo shows the performance boost that BindOnce can give to your UI.
In order to test the UI reactivness try to press and hold a key inside the input field, when the AngularJs watchers list is small you'll see the character displayed in both the view and the input with the same smooth speed. Once you start loading a large amount of persons in the table AngularJs become unresponsive and pressing a key in the input will freeze the UI. Using BindOnce you can load as many persons as you want and the UI will be still reactive.
Here you can try the same test using only AngularJs so you can see the difference: http://plnkr.co/edit/jwrHVb?p=preview