Using AngularJS $scope within OpenCPU - javascript

I have an alright knowledge of angularjs but I am more of a R programmer and I have therefore being experimenting with OpenCPU js library.
One thing I can't get my head around is why I can't assign the output from a simple API request to the public OpenCPU server, rnorm(n = 2) function, to an angular $scope. What baffles me is that I can use jquery to assign the returned json via ID for example.
From what I understand it is best practice not to mix jquery into the angular controller. Am I right in thinking this?
Working with Jquery
app.controller('rCtrl', function($scope){
req = ocpu.rpc('rnorm',{
n : 2
}, function(output){$('#output').text(output)});
})
Not Working $scope
app.controller('rCtrl', function($scope){
req = ocpu.rpc('rnorm',{
n : 2
}, function(output){$scope.normalValues = output)});
})

Since you are using a non-angular tool you are assigning $scope.normalValues outside of the Angular digest loop. Use a $scope.apply() to fix this:
app.controller('rCtrl', function($scope){
req = ocpu.rpc('rnorm',{
n : 2
}, function(output){
$scope.$apply(function(){
$scope.normalValues = output;
});
)});
});
You can also just call $scope.$apply() right after you set your scope value but I personally like the callback syntax since it makes it easier to see why you use it.

I'm guessing it's because your function never triggers a $digest cycle - so you'd have to force one with $timeout
app.controller('rCtrl', function($scope, $timeout){
req = ocpu.rpc('rnorm',{
n : 2
}, function(output){
$timeout(function() { $scope.normalValues = output })
})
})

Related

Inject a variable from Service to html

I am asked to debug some things in an angular JS app, problem is I dont know anything about this framework and I need to get this done.
I need to inject a variable from my service to a html template.
So I thought I will need to get this variable from Controller, which get it from the Service.
For the moment I have this :
controller.js
$scope.fileURL = null;
var fileURL = ItemsService.fileURL;
$scope.fileURL.push(fileURL);
services.js
I declare this inside my service class :
this.fileURL = null;
and i declare it my method this way :
self.fileURL = fileURL;
But I got this error TypeError: Cannot call method 'push' of null
And fileURL is defined and got a value in my method.
Any idea why ?
Thanks
more performant solution
Thanks to maurycy for his comments.
Making your service visible through $scope like this:
$scope.itemService = ItemService;
and using it in your template for example like this:
{{itemService.fileURL}}
will be more perfomant, less complex and have all other advantages as well.
old solution
Why don't you just pass through your variable:
In your service:
this.fileURL = "something";
in your controller:
$scope.fileURL = function() {
return ItemsService.fileURL;
};
This way changes made in your service (like a update of fileURL will trigger an update of the view through the controller.
FYI:
If you define your $scope-variable like this:
Object.defineProperty($scope, 'fileURL', {
get: function() {
return ItemService.fileURL;
},
set: function(newValue) {
ItemService.fileURL = newValue;
}
});
You may also update the variable in the service from the controller AND childscopes will have the same functionality, since upon $scope.fileURL = 'different'; they won't introduce a new property fileURL which hides the original one and doesn't wire to the service anymore.

Angular controller undefined within jasmine test

I'm currently having an issue writing some tests for a controller. Within the beforeEach block below I need to instantiate an activityController and inject the scope object. I have added a console log before the call to the $controller service and this is outputted however the one after never gets called therefore something is breaking within the $controller block.
beforeEach(inject(function($controller) {
console.log(activityController);
activityController = $controller('activityController', {
'$scope': $scope
});
console.log("TEST");
}));
Within my tests I'm seeing Type Error: activityController is undefined in C:\.......\activity.controller.test.js so I know it's definitely not being instantiated.
I've created a gist of the relevant files here: https://gist.github.com/junderhill/e181ce866ab1ebb1f805
The activity controller not being instantiated correctly is causing my tests to fail. Any ideas on what may be causing this would be appreciated. Thanks
Jason.
Try to set activityService whilst creating controller, because you should also inject all services.
Looks like this line may be causing the problem:
mockRoleService.setCurrentRole({"AssignmentID":21,"EndDate":"2049-12-31T00:00:00","StartDate":"2000-01-01T00:00:00","UserType":1,"AccessLevel":"00000000-0000-0000-0000-000000000000","Description":"Demonstration Territory 1","TeamID":null});
It looks like you're using an actual injected version of your roleService instead of a stubbed literal, so it's actually going to fire off your implementation, which is...
this.setCurrentRole = function(role){
currentRole = role;
$http.get("http://localhost:14938/api/User/GetTeamForAssignment?assignmentId=" + role["AssignmentID"] + "&assignmentType=" + role["UserType"])
.success(function (data) {
currentTeam = data;
});
}
If you're going to use that service directly with an $httpBackend mock, I'd actually wrap that operation in a $q.defer(), because currently as that stands, that is an asychronous call. You'll want that operation to complete to set the currentTeam properly. So, maybe something like..
this.setCurrentRole = function(role){
var deferred = $q.defer();
currentRole = role;
$http.get("http://localhost:14938/api/User/GetTeamForAssignment?assignmentId=" + role["AssignmentID"] + "&assignmentType=" + role["UserType"])
.success(function (data) {
currentTeam = data;
deferred.resolve();
});
return deferred.promise;
}
And obviously do a deferred.reject of some sort if something wonky comes back from HTTP.
Hope that helps!
Eric

How to get access to AngularJS in Jquery?

Recently I have begun to integrate AngularJS in project.
Before I have written many prototypes and single functions in JavaScript, for example (Node.js + socket.io functionality).
Today I a have trouble communicating AngularJS with clear JavaScript:
JS:
socket.on('message', function (data) {
showSystemMessage();
}
function showSystemMessage(message) {
// Increment here AngularJS $scope.messagesCnt++ ?;
}
AngularJS:
.controller('MessagesController', ['$scope', function($scope) {
$scope.messagesCnt = 0;
}])
HTML:
<div>{{messagesCnt}}</div>
Please, attention to method: showSystemMessage()
Ideally, You should follow what #Yaseer has said, but i see, that you're using Socket IO native implementation [No angular Wrapper around].
Hence, you have two solutions :
Use Angular Socket IO
Access Angular Controller from the native javascript :
For this you must have an element with an identifier ID. then you can use the id to access the associated scope.
angular.element("#your-identifier-id-here").scope().messagesCnt++;
Write your socket listener code inside controller
function appcontroller($scope){
socket.on('message', function (data) {
showSystemMessage();
}
function showSystemMessage(message) {
$scope.$apply(function(){
// Increment here AngularJS $scope.messagesCnt++ ?;
});
}
}
If you function showSystemMessage is outside the controller scope, there is no way you can update the scope variable messagesCnt. (There are but not straight forward.)
Instead this function of yours should reside in an angular service instead, and then on whatever event you want you could broadcast a message from your service to your controller to update its count value.

Injecting service which define by module.provider

Sorry to ask something like this, but i m already spend couple of days to solve this one.
But i m really need help. I am already read Understanding Dependency Injection
and also other stack question use $http inside custom provider in app config use the
$injector
on run block also not work in my code.
Perhaps someone here can help me, i am also worried how annotate the injection on my provider for minification.
My code in
Here
The problem is that when you call $http in the _getItem you are in the "controller". A solution could be to do this:
this.$get = function($http) {
return {
mainUrl : _mainUrl,
getItem : _getItem,
httpWrapper : $http
};
And then in the _getItem assign (or use the httpWrapper directly):
var $http = this.httpWrapper;
In order to avoid problems with the minification, you could add the injection to the method $get:
this.$get = ['$http', function($http) {
Here the updated Plunker: http://plnkr.co/edit/m7oXNolo6iV8Zy1NJ0vx
EDIT: I think that what you wanted to achieve is this:
var _getItem = function() {
var _d = null;
console.log(this)
var $http = this.httpWrapper;
var $q = this.qWrapper;
_d = $q.defer();
$http.get(_mainUrl)
.success(function(data) {
console.log(data);
_d.resolve( {data: data, x: "efe"} );
})
.error(function(status) {
_d.resolve( status );
});
return _d.promise;
};
$q.defer() allows to defer the http call to your controller, then on your controller you have to edit this:
facade.getItem().then(function(data){
$scope.myReturn = data;
}
Updated Plunker: http://plnkr.co/edit/xR1d3KnWhX51jHHZ8t3m
Note: Consider that the nature of then is asynchronous, thus if you use the variable straight afterwards, it still will be undefined

How to create reset() method in Service that return promise?

I've got a service called MyArticles. Using $http GET, collects all articles for a given Category. The MyArticles Service is injected in ControllerA, ControllerB, ControllerC, that should run some commands after MyArticles Promise is resolved.
Works after first initialisation, but I don't know what to do if I need to reset() the loaded data for MyArticles, since the commands in the ControllerA, ControllerB, ControllerC only runs the first time, after the promise is resolved. For example, what if I'd like to get Articles from a different Category ?
I'm trying to find a pattern for this and I wrote the following, I guess it helps to understand what I'd like to achieve:
var MyApp = angular.module('MyApp', []);
MyApp.config(function($locationProvider){
$locationProvider.hashPrefix('!');
});
MyApp.factory('MyService', function($q,$timeout){
var deferred;
var loadData = function(){
deferred = $q.defer();
$timeout(function(){
deferred.resolve({
myData: "test"
});
}, 250);
};
return {
reset: function(){
loadData();
},
getPromise: function(){
return deferred.promise;
}
};
});
MyApp.controller('MyCtrl', function($scope,MyService){
$scope.foo = "Service share data";
MyService.reset();
MyService.getPromise().then(function(data){
console.log(data);
});
});
*the example is also available at: http://jsbin.com/OCaNehe/2/
I wonder what I can do, if I need a service - using promises - that should be able to refresh data and the service is being injected in different Controllers, etc ?
Thanks for looking!
Another alternative is to use watches. See: http://plnkr.co/edit/auovRxGPViyflUVPvG1A?p=preview. It might be easier to maintain compared to $emit/$broadcasts later on, especially if you end up having tons of services along with directives and controllers that use them.
Also you might want to think about using the natural scope inheritance angular has, but that depends on your application.

Categories

Resources