Category Archives: AngularJS

Socket.IO AngularJS Wrapper

I’ve been playing around with Socket.IO and AngularJS. To make things easier I created this service which can be used for transferring data between the client (which could be a web page) and a NodeJS server.

The app is served by NodeJS so the Socket.IO server is listening on same location.

'use strict';

angular
.module('APP')
.factory('$WS', function($rootScope) {
    var self = this;

    self.ready = false;

    self.socket = io.connect(location.host, {
        'connect timeout':       100,
        'reconnection delay':    100
    });

    self.socket.on('init', function() {
        console.log('init');
    });

    self.socket.on('disconnect', function() {
        console.log('socket disconnected');
    });

    self.socket.on('connect', function() {
        console.log('socket connected');
    });

    return {
        ready: function(callback) {
            if(self.ready) {
                callback();
                return;
            }

            self.socket.on('connect', function() {
                $rootScope.$apply(function() {
                    self.ready = true;
                    callback.apply(self.socket);
                });
            });
        },
        on: function(eventName, callback) {
            self.socket.on(eventName, function() {
                var args = arguments;

                $rootScope.$apply(function() {
                    callback.apply(self.socket, args);
                });
            });
        },
        emit: function(eventName, data, callback) {
            self.socket.emit(eventName, data, function() {
                var args = arguments;
                $rootScope.$apply(function() {
                    if(callback) {
                        callback.apply(self.socket, args);
                    }
                });
            });
        }
    };
});

Usage:

angular
.module('APP')
.controller('TestController', ['$scope', '$WS', function($scope, $WS) {

    $scope.messages = [];

    // Connect websocket
    $WS.ready(function() {
    
        // Receive message
        $WS.on('chat/message', function(data) {
            
            // Validate input data
            if(data.message_id) {
                console.log(data);
                $scope.messages.push(data);
            }
        });
    });

    // You can add another ready state listener for the same connection
    // Let's consider we have a method which sends messages
    $scope.send_message = function(msg_title, msg_value) {
        
        $WS.ready(function() {
            // Emit message
            $WS.emit('chat/message', {
                title:    msg_title,
                message:  mgs_value
            });
        });
    };

}]);

 

This is just basic usage.  Will be back with NodeJS & Socket.IO server example.

AngularJS Input Max Length Directive

In case you need to set a max length to a model binded input, well check this directive:

'use strict';

angular
.module('APP')
.directive('uiMaxlength', function() {
    return {
        require: 'ngModel',
        link: function(scope, el, attrs, model) {
            var max_length = parseInt(attrs.uiMaxlength, 10);

            var input_value_parser = function(value) {
                if(value.length > max_length) {
                    value = value.substring(0, max_length);
                    model.$setViewValue(value);
                    model.$render();
                }

                return value;
            };

            model.$parsers.push(input_value_parser);
        }
    };
})

;

Usage:

<input ui-maxlength="10"
       type="text"
       name="input_name"
       ng-model="model_name" />

With some minor changes this directive can also be used for setting Min Length.

AngularJS Ng-Repeat In Range

AngularJS does not provide a way to create multiple copies of an element.

Still this behavior is easy to achieve. Check the bellow filter which solves this problem:

'use strict';

angular
.module('APP')
.filter('range', function() {
    return function(input, total) {
        total = parseInt(total, 10);

        for(var i=0; i<total; ++i) {
            input.push(i);
        }
    
        return input;
    };
})

;

Usage:

<div ng-repeat="n in [] | range:10">element copy #{{$index}}/10</div>

 

 

AngularJS Custom Dropdown Time Filter

I’ve created this filter to allow hour selection using HTML dropdown.

The filter accepts as input three paramers: the starting hour, the ending hour, and the minute interval.

var app = angular.module('APP', ['APP.filters']);

app.controller('MainController', ['$scope', function($scope) {
 
}]);

angular.module('APP.filters', []).filter('time', function() {
    return function(input, from, to, interval) {
        from     = parseInt(from, 10);
        to       = parseInt(to, 10);
        interval = parseInt(interval, 10);

        for(var i=from, y=0; i<=to; ++i, y+=interval) {
            for(var y=0; y<60; y+=interval) {
                input.push(((i % 12) || 12)+ ":" + (y===0?'00':y) +" " + (i>12?'pm':'am'));
            }
        }
    
        return input;
    };
});

Usage:

<div ng-app="APP" ng-controller="MainController">
    <select>
        <option ng-repeat="h_m in [] | time:8:20:60">{{h_m}}</option>
    </select>
</div>

The above filter time:8:20:60 will output all the hours starting with 8 AM – 8 PM

The starting/ending hour must be between 0-24.

The interval can be between 1-60.

 

The filter can be used for showing multiple minutes in an hour.

For example time:10:14:15 will output 10:00 am, 10:15 am, 10:30 am, … , 13:45 pm, 14:00 pm.

 

AngularJS Cookie Service

In case you’re searching for a cookie service that can be used in AngularJS, here it is:

 

'use strict'

angular
.module('APP.services', [])
.factory('Cookie', function() {
	var self = this;

	self.set = function(name, value, days) {
		var expires = "";

		if(days) {
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			expires = "; expires="+date.toGMTString();
		} else {
			expires = "";
		}

		document.cookie = name + "=" + value + expires + "; path=/";
	};

	self.get = function(name) {
		var nameEQ	= name + "=",
			ca		= document.cookie.split(';');

		for(var i=0; i<ca.length; ++i) {
			var c = ca[i];
			while(c.charAt(0)==' ') {
				c = c.substring(1,c.length);
			}

			if(c.indexOf(nameEQ) === 0) {
				return c.substring(nameEQ.length,c.length);
			}
		}

		return null;
	};

	self.remove = function(name) {
		self.put(name, "", -1);
	};

	return {
		set:	self.set,
		get:	self.get,
		remove:	self.remove
	};
})

;

Usage:

'use strict'

angular
.module('APP.home', ['APP.services'])
.controller('TestController', ['Cookie', function(Cookie) {

    // Set cookie
    Cookie.set('cookie_name', 'VALUE', 1);

    // Get cookie
    if(Cookie.get('cookie_name')) {
        console.log(Cookie.get('cookie_name'));
    }

    // Remove cookie
    Cookie.remove('cookie_name');

}])

;

 

Load Google Maps Library on the fly

Define the service:

'use strict';

angular
.module('APP.services')
.factory('GMAPS', ['$window', function($window) {
    var self        = this,
        callback    = null;

    $window.gmaps_loaded = function() {
        if(callback) {
            callback();
        }
    };

    self.load = function(cb) {
        if($window.google) {
            cb();
            return;
        }

        callback = cb;

        var gmaps_script = $window.document.createElement('script');

        gmaps_script.type = 'text/javascript';
        gmaps_script.src  = 'https://maps.googleapis.com/maps/api/js?v=3.exp&callback=gmaps_loaded&client=your_client_id';
        $window.document.body.appendChild(gmaps_script);
    };

    return {
        'load': self.load
    };
}])

;

Usage:

'use strict';

angular
.module('APP.home', ['APP.services'])
.controller('TestController', ['GMAPS', function(GMAPS) {

    // Load Google library and initiate it
    GMAPS.load(function() {
        var map = new google.maps.Map(element_id, options);
    });

}])

;