CodeSnips

Saturday, July 19, 2014

AngularJS Number Validator Directive

After some searching yielded a few hints and examples, none of which really worked all that well, I pieced this together. Hopefully others will find it useful.

This AngularJS directive validates numeric entry. It uses a regular expression to test whether the input matches the expected numeric format and set the validity state of the element.

How does this work?
The $parsers array is an array of functions which can test the value on the input element. They pass the value along to other parsers by returning the value.  I change the value by removing any commas so the returned numeric string can be used as a Number.

In the directive, I capture the value of the directive attribute and add a parser function and formatter function to the respective arrays passed in.

The $formatters array is an array of functions which can format the model value for display in the input element. I use the built-in "numberFilter" for this.



View/Run/Edit the example in Plunker


app.directive('isNumber', ['numberFilter',function(numberFilter){
    return{
        require:'ngModel',
        link: function(scope, elem, attrs, ctrl){
            var digits = attrs.isNumber.length===0 ? "2" : attrs.isNumber;
            ctrl.$parsers.unshift(checkForNumber);
            ctrl.$formatters.unshift(formatNumber);

            function checkForNumber(viewValue){

                // Checks for positive or negative decimal or integer number with or without thousand separators
                if (/^-{0,1}\d{1,3}(,\d{3})*\.{0,1}\d*$|^-{0,1}\d*\.{0,1}\d*$/.test(viewValue)) {
                    ctrl.$setValidity('isNumber',true);
                }
                else{
                    ctrl.$setValidity('isNumber', false);
                }
                return viewValue.replace(/,/g,'');
            }

            function formatNumber(viewValue) {
                return numberFilter(viewValue,digits);
            }
        }
    };
}]);

Sunday, July 13, 2014

MEAN Stack CRUD Example

I thought it would be useful to create a full example using the MEAN stack. I wanted to include most of the bells and whistles in this particular example so that it would serve as a useful reference for other more complex applications.

MEAN is an acronym which stands for "Mongo Express Angular Node", and I must say this stack lets you create some very mean (and lean) code. 

The source for the full example is angularExample on GitHub - the README.md tells you how to run it.

Points of interest

  • The 'seeddb' script shows how to run Mongo command and run a Javascript setup script which creates the database and seeds the Account and AccountType collections. It creates a unique index on the Accounts collection.
  • The app.js file in the project root folder has the setup for Express, it passes the configured express handler as a "module.exports = app" - which is used by the (bin/www) script to setup the server listener.
  • Client-side setup of Socket.IO can be found in (/public/views/layout.jade) last two lines. This creates a global "socket" variable for client-side javascript to use for sending/receiving events. 
  • The application uses Socket.IO to broadcast account update notifications to the client browsers using the application.  See the bin/www file on how server-side Socket.IO is plugged in - along with the event send/receive.
  • The AngularJS controller (/public/javascripts/app/accountController.js) has the Socket.IO client code which sends notifications after saving/deleting items, and listens for the broadcast event in order to refresh the account list.
  • The (/routes/index.js) file has all the route handlers for the REST "/api" routes and home page load.