What best way use in Angular in my case? - angularjs

I need write some methods that works with socket.io in Angular JS.
SendMessage()
GetMessages()
TypingMessage();
For example, after event ng-click="SendMessage()" I need send message via Socket.io.
I have wrote a good tutotial in Stack overflow about service and factory Angular JS. But still can not choose right way what use in my case. Put this methods in Factory method or make service?

I would suggest you have a look at the following git repo:
https://github.com/btford/angular-socket-io
I use this in combination with a Python socket server and it works great. You will be able to create your own socket factory from btford's socketFactory which you can use as a normal factory.
angular.module('myApp', [
'btford.socket-io'
]).
factory('mySocket', function (socketFactory) {
var myIoSocket = io.connect('/some/path');
mySocket = socketFactory({
ioSocket: myIoSocket
});
return mySocket;
});

Related

Should I attach a config to $rootScope or repeatedly call injected factory?

I have some data in my firebase server that provides settings for client apps.
I've implemented a factory that gets this data from the server.
My question is regarding design - should I get this data once and application start and attach it to rootscope and pass that to all controllers needing it or inject my factory into every controller that uses the config data and internally in the factory store the config locally?
// this factory allows getting various global app settings and constants
.factory('ConfigFactory', ['$firebaseObject', 'FirebaseConfig',
function($firebaseObject, FirebaseConfig) {
'use strict';
var configs = new Firebase(FirebaseConfig.baseUrl + "/configs");
var _configs = [];
return {
getConfig: function(configName, user_id){
if( !_configs[configName]){
_configs[configName] = $firebaseObject(configs.child(configName));
}
return _configs[configName];
}
};
}
])
The good practice is to use a service and inject this service where you need that information.
Note that what you're defining is not a factory, but a service. The factory is the function used to create the service, and the fact that you're using factory() rather than service() or provider() to define this service is an implementation detail.
The service is thus named badly. In should be named "configuration", rather than "ConfigFactory". Services usually start with a lowercase letter.

how to make library of primary functions in AngularJS

I want to develop set of functions(sort of library) for CRUD in AngularJS so I can reuse them for couple of entities of my project. For server communication I made factory of $resource and using accordingly. $resource factory looks like this:
Model File:
var get_entity_model = angular.module("app.getentity", []).factory('getEntity', ['$resource', function($resource) {
return{
entity_view: $resource(baseurl+'/rest/'+serviceName+'/entity/:id/?app_name='+appName+'&fields=*', null, {'update': { method:'PUT' }})
}
}]);
And here how I'm using it in controller
Controller File:
getEntity.entity_view.get(
function(entity_list){
},
function(error){
}
)
Here entity_view is the table name. I'm passing all related functions like pagination and sub request to get the data of related tables etc code I put into success function of above request.
Now I want to make a library where I can define all this stuff and simply by calling the function I should be able to get all this stuff like:
entity.getEntity()
Should return same result as above code.
I tried with creating factory for above task but seems it need callback function and function at factory will return only data which I'm already getting from my model file so I need to make it compact and easy to use.
Factory Code at factory file:
var api = angular.module("app.entity_api", []).factory('entity_factory', ['$resource','getEntity',function($resource,getEntity) {
var entity_factory = {};
entity_factory.get_entity = function(callback){
getEntity.entity_view.get().$promise.then(
function(data){
callback(data.record);
}
);
}
return entity_factory;
}]);
And here how I call the function in controller:
Controller code:
api.controller("sample",['entity_factory','getEntity','$scope',function(entity_factory,getEntity,$scope){
$scope.init = function(){
entity_factory.get_entity(
function(data){
console.log(data);
}
);
}
$scope.init();
}])
Problem is that my entity_factory code will return only the data from server rest of the additional code I've to do in callback function which seems not much difference than my current exercise. So, the question is how can I achieve my goal to make a library of functions with additional code which return complete compiled result to make the code reusable for other entities and compact.
I like that you're a thinking of making a library but in this case, don't reinvent the wheel and save your precious time. Check out Restangular and your task will be a lot easier. Restangular is an AngularJS service that simplifies common GET, POST, DELETE, and UPDATE requests with a minimum of client code. It's a perfect fit for any WebApp that consumes data from a RESTful API.

Using Angular with socket.io

I know that Angular provides awesome two way data binding on the client side, but I want more!
I'm looking for the right way to hook up angular with my server side (SailsJS which includes socket.io).
Thanks!
Have you tried angular-sails-bind? (https://github.com/diegopamio/angular-sails-bind) I bet you haven't, as I've just released to the world a couple of minutes ago :). I made it for my own project and then decided to put it as a separated library so everybody could benefit and I could have my first experience developing a bower package.
I hope it could help you.
BTW: it works with sails 0.10 (as some things, like topic names had changed since 0.9). If you need to make it work with 0.9, just let me know and I'll happy to help.
I would recommend trying out https://github.com/btford/angular-socket-io that allows to simply use socket object in your controllers like that:
var socketApp = angular.module('socketApp', [
'btford.socket-io'
]);
socketApp
.controller('messageListController', ['$scope', 'socket', function($scope, socket) {
$scope.messages = [];
$scope.postMessage = function(message) {};
socket.on('connect', function () {
$scope.$on('socket:update', function(event, data) {
$scope.messages.push(data);
});
$scope.postMessage = function(message, callback) {
socket.emit('post', message, function(commitedMessage) {
$scope.messages.push(commitedMessage);
callback(commitedMessage);
});
};
});
}]);

angularJS unit testing where run contains a HTTP request?

I am fairly new to AngularJS and am trying to learn some best practices. I have things working, but would like to start adding some unit tests to my modules and controllers. The first one I am looking to tackle is my AuthModule.
I have an AuthModule. This Module registers a Factory called "AuthModule" and exposes things like "setAuthenticatedUser" and also fields like "isLoggedIn" and "currentUser". I think this is a fairly common pattern in an AngularJS application, with some variations on the specific implementation details.
authModule.factory(
'AuthModule',
function(APIService, $rootScope) {
var _currentUser = null;
var _isLoggedIn = false;
return {
'setAuthenticatedUser' : function(currentUser) {
_currentUser = currentUser;
_isLoggedIn = currentUser == null ? false : true;
$rootScope.$broadcast('event:authenticatedUserChanged',
_currentUser);
if (_isLoggedIn == false) {
$rootScope.$broadcast('event:loginRequired')
}
$rootScope.authenticatedUser = _currentUser;
$rootScope.isLoggedIn = _isLoggedIn;
},
'isLoggedIn' : _isLoggedIn,
'currentUser' : _currentUser
}
});
The module does some other things like register a handler for the event "loginRequired" to send the person back to the home screen. These events are raised by the AuthModule factory.
authModule.run(function($rootScope, $log, $location) {
$rootScope.$on("event:loginRequired", function(event, data) {
$log.info("sending him home. Login is required");
$location.path("/");
});
});
Finally, the module has a run block which will use an API service I have to determine the current logged in user form the backend.
authModule.run(
function(APIService, $log, AuthModule) {
APIService.keepAlive().then(function(currentUser) {
AuthModule.setAuthenticatedUser(currentUser.user);
}, function(response) {
AuthModule.setAuthenticatedUser(null);
});
});
Here are some of my questions:
My question is how would you setup tests for this? I would think that I would need to Mock out the APIService? I'm having a hard time because I keep getting unexpected POST request to my /keepalive function (called within APIService.keepAlive())?
Is there any way to use $httpBackend in order to return the right response to the actual KeepAlive call? This would prevent me from having to mock-out the API service?
Should I pull the .run() block out which obtains the current logged in user out of the AuthModule and put it into the main application? It seems no matter where I put the run() block, I can't seem to initialize the $httpbackend before I load the module?
Should the AuthModule even be its own module at all? or should I just use the main application module and register the factory there?
Run blocks are the closest thing in Angular to the main method. A run block is the code which needs to run to kickstart the application. It is executed after all of the service have been configured and the injector has been created. Run blocks typically contain code which is hard to unit-test, and for this reason should be declared in isolated modules, so that they can be ignored in the unit-tests.angularjs docs
I suggest you take a look at this authentication service, using a service is the way to go.
Hopefully this would help ... Good luck

syncing the views of two angular apps

I have two angular applications in one page, and I need them to communicate. Specifically, I want one application to use a service of another application.
I am able to get the service of the other application using Injector.get(service), but when I change the data using the service in one application, it does not reflect in the view of the other, even though both are supposed to show the same data. You can see a simplified version of the problem in jsFiddle.
To save you the click, this is the relevant script:
//myAppLeft - an angular app with controller and service
var myAppLeft = angular.module('myAppLeft', []);
myAppLeft.factory('Service1',function(){
var serviceInstance = {};
serviceInstance.data = ['a','b','c','d','e'];
serviceInstance.remove = function(){
serviceInstance.data.pop();
console.log(serviceInstance.data);
};
return serviceInstance;
} );
myAppLeft.controller('Ctrl1', ['$scope', 'Service1', function($scope, service1) {
$scope.data = service1.data;
$scope.changeData =function(){
service1.remove();
}
}]);
var leftAppInjector = angular.bootstrap($("#leftPanel"), ['myAppLeft']);
//myAppRight = an angular app with controller which uses a service from myAppLeft
var myAppRight = angular.module('myAppRight', []);
myAppRight.controller('Ctrl2', ['$scope', function($scope) {
$scope.data = leftAppInjector.get('Service1').data;
$scope.changeData =function(){
leftAppInjector.get('Service1').remove();
}
}]);
var rightAppInjector = angular.bootstrap($("#rightPanel"), ['myAppRight']);
I'd be happy to know why my code does not work as expected, and would be even happier to know if and how such thing can work.
I understand that if instead of two angular-apps I would have used one angular-app with two modules this would have worked just as I wanted, but unfortunately I cannot adopt this approach because my application consists of a pure-js core with extensions, each extension can be written in a different library/platform and I want my extensions to be angular ones.
Thanks,
Nurit.
Angular apps are separate entities, even if you use the same service in both. the second app just initializes its own version off it.
What you want can be done using localStorage, and the storage events.
Ping me if you need additional help on this!

Resources