Word count in AngularJS

I am trying to write a quick program that counts the number of words in AngularJS. Basically a textarea in HTML and underneath it should display the number of words as the user inputs them.

So this is my HTML code:

 <!doctype html>
 <html ng-app>
 <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.min.js"></script>
    <script src="wordcount.js"></script>
 </head>
 <body>
    <div ng-controller="wordCount">
        <label>Copy and Paste your text:</label><br>
        <textarea cols="80" rows="20" ng-model="mytext"></textarea>
        <hr>
        <span>{{wordCount()}} word(s)</span>
    </div>
 </body>
</html>

And here is my Javascript file called wordcount.js (to count the number of words in a given string):

function wordCount($scope) {
    $scope.numberofwords = function(s) {
        s = document.getElementById("mytext").value;
        s = s.replace(/(^\s*)|(\s*$)/gi,"");
        s = s.replace(/[ ]{2,}/gi," ");
        s = s.replace(/\n /,"\n");
        return s.split(' ').length;
    }
}

I basically found the above on http://www.mediacollege.com/internet/javascript/text/count-words.html

So I have probably not fully understood how to use AngularJS (and the JS code is probably wrong too) to update the number of words instantly. Right now it doesn't show anything but "words".

Does anyone have an idea?

One of correct way is to use a $scope function:

<body ng-controller="WCController">
    <h3>World count</h3>
    <div>total words: <span ng-bind="countOf(myText)"></span></div>
    <textarea ng-model="myText"></textarea>
</body>

and at the controller:

$scope.countOf = function(text) {
    var s = text ? text.split(/\s+/) : 0; // it splits the text on space/tab/enter
    return s ? s.length : '';
};

You can test this on plunker: http://run.plnkr.co/Mk9BjXIUbs8hGoGm/

Solution

  • update a wordCount property when myText changes.
  • use simple regexp in a String.prototype.match call.
  • use this updated wordCount scope property in your template.

Code

Your watcher should look like something like that:

$scope.$watch('myText', function(text) {
    // no text, no count
    if(!text) {
        $scope.wordCount = 0;
    } 
    // search for matches and count them
    else {
        var matches = text.match(/[^\s\n\r]+/g);
        $scope.wordCount = matches ? matches.length : 0;
    }
});

Important note

Why computing the count in a watcher ?

To prevent this count from being computed on each digestion, the way it is when you use such a wordCount() method call in your template !