Using Angular with socket.io - angularjs

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);
});
};
});
}]);

Related

Is it possible to resolve AngularJS promises in a template?

in all documentation and tutorials for HTTP request i found that recomanded usage is something like:
var ax = {
getCaseData: function() {
api.cases.getCase(caseManager.data.id).then(function(res){
// puting my response to $scope.something
$scope.something = res.data;
});
},
}
I really don't feel like senior so please tell me if I am wrong but I thing many times you don't need to store something like this on scope, for example you want to just resolve promise once and display data (you are not doing anything else with it)
So I was thinking if is there an option to make a promise as:
var ax = {
getCaseData: function() {
return api.cases.getCase(caseManager.data.id);
},
}
and after this call tempalte something like:
<li ng-repeat="ax.getCaseData()"></li>
This was handled automatically in old version of AngularJS (<1.2), but was removed since then.
Some posts state that the feature can be re-enabled manually by adding this line in your ".config" function :
$parseProvider.unwrapPromises(true);
But this is not advised as a solution. You are currently doing it the right way.
If you have plenty of cases like this, you can probably create your own "promises wrapper" function, and use it from your template.
See : https://stackoverflow.com/a/19472065/1636977

What best way use in Angular in my case?

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;
});

Angularjs Passing array between controllers

I have been through several tutorials and posts about this topic and still can't seem to figure out what is wrong with my code. To me it seems I am having scoping issues with the data within my service. My code is split up into separate files. Here is my code:
github link : https://github.com/StudentJoeyJMStudios/PetPinterest.git
//in dataService.js
var app = angular.module('se165PetPinterestWebApp');
app.service('SharedData', function ()
{
var categoryOfSelectedAnimals = [];
this.setCatOfSelAnimals = function(pulledCategoriesFromParse)
{
categoryOfSelectedAnimals = pulledCategoriesFromParse;
console.log('after assignment in set::' + categoryOfSelectedAnimals);
};
this.getCatOfSelAnimals = function()
{
console.log('in get::::' + categoryOfSelectedAnimals);
return categoryOfSelectedAnimals;
};
});
in my first controller to set the data in signup.js
app.controller('SignupCtrl',['$scope', 'SharedData', function ($scope, SharedData)
{
var Categories = Parse.Object.extend('Categories');
var query = new Parse.Query(Categories);
query.find({
success: function(results)
{
$scope.availableCategoriesOfAnimals = results;
SharedData.setCatOfSelAnimals(results);
},
error: function(error)
{
alert('Error: ' + error.code + ' ' + error.message);
}
});
};
}]);
Then in my other controller trying to get the data from the array within my service:
var app = angular.module('se165PetPinterestWebApp');
app.controller('CatSelCtrl', function ($scope, SharedData)
{
$scope.availableCategoriesOfAnimals = SharedData.getCatOfSelAnimals();
});
When I print the contents from the SharedData.getCatOfSelAnimals I get 0 every time. Please help. Thank you very much in advance.
EDIT: After playing around with a string a bit I am finding the changed string in the set function is not saved into the service and when I call my get function within my service the string is not changed from the set method. Please help, thank you in advance.
EDIT: So it looks like when I navigate to new page by using window.location.href = '../views/categorySelection.html'; in my signup.js it reloads my dataService.js which re-sets my variables back to nothing. Does anyone have any ideas as to how to fix this?
Edit
First: why you lose data
You need to setup routing properly. Right now you are not changing views but rather using window.location.href to load a new bootstrap file (dashboard.html), i.e. everything saved in memory will be lost. So you have been doing it right, sort of, but the moment you change to dashboard.html all data from Parse is lost.
You can solve this by configuring routes and use $location.url() to change URL. Read more about angular.route here: https://docs.angularjs.org/api/ngRoute/service/$route
The angular way
After looking at your code and running your app I think we need to take a step back. Angular is tricky to get used to but there is a lot of good tutorials. I think you might wanna read some of them to get a better grasp of how it works and how to setup and build your app.
Start here: http://www.airpair.com/angularjs
Boilerplate
Found this boilerplate for an Angular app using Parse. It might be something you could use. https://github.com/brandid/parse-angular-demo
Original
Or an even quicker way to empty $scope.availableCategoriesOfAnimals and then merge new data without breaking reference:
$scope.availableCategoriesOfAnimals.length = 0;
Array.prototype.push.apply($scope.availableCategoriesOfAnimals, pulledCategoriesFromParse);
You are breaking the reference on assignment. This is a JavaScript issue, not an angular one for that matter ;)
Try this in your set function:
categoryOfSelectedAnimals.length=0;
pulledCategoriesFromParse.forEach(function (e) {categoryOfSelectedAnimals.push(e)});
in stead of reassigning
edit: angular extend works on objects, not arrays, so replaced it with a bit of JS.

Angular controller not accessible in production

I have a Symfony project, and as the vast majority working on more than one environments: dev and production, using Angular.js.
At the moment, I have got an Angular controller which is accessible in dev environment, but not in production, throwing the message: "Error: [ng:areq] Argument 'xxxx' is not a function, got undefined".
I have seen the latter message in several threads but none of them helped me.
angular.module('MyApp').controller('MyController', function MyController($scope, MyMapper, _, moment, APP_URL, $location) {
$scope.APP_URL = APP_URL;
$scope.momentjs = moment;
$scope.isLoading = 1;
$scope.page = 1;
$scope.totalPagesNum = 1;
$scope.limit = 20;
// fill the table with data
MyMapper.find($location.search()).then(function(data) {
// ...
})();
}).then(function() {
$scope.isLoading = false;
});
});
If you are minimizing your code (as would be typical in production), you will want to annotate your dependencies since they may get renamed by the minimization script. In order to do this, use the following pattern for your code:
angular.module('MyApp').controller('MyController',
['$scope','MyMapper','_','momemt','APP_URL','$location',
function($scope, MyMapper, _, moment, APP_URL, $location) {
/* your code for the controller */
}
]
);
Please see https://docs.angularjs.org/guide/di for more information, particularly the "Dependency Annotation" section and the inline array notation subsection.
I think the issue is pretty much solved.
It turns out that the minified version of vendors.js (vendros.min.js), was not properly loaded in the production environment. Therefore, I had to point to the correct one in my Gruntfile.js.
Secondly, I refactored my controllers according to AngularJS online guide, as per Brad.
Thanks everyone involved.

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