Reference Error in API function call using AngularJS - angularjs

formApp.controller('load', function ($scope, ApiCall, $window, $http) {
$window.onload = function () {
alert("the page loaded and will now call the function");
ApiCall.GetApiCall("signOn", "GetSingleSignOn").success(function (data) {
alert("successful call to singleSignOn, GetSingleSignOn");
var data = $.parseJSON(JSON.parse(data));
$scope.apiGetInfo = data;
alert("successful call to singleSignOn, GetSingleSignOn");
alert(data);
});
};
This code works fine up to the var data- $.parseJson(JSON.parse(data));
I looked at some examples of how to do this in the Controller online and they all looked this way with $.parseJSON(JSON.parse(data)).
It gives me: ReferenceError: $ is not defined
Not sure why as every example I looked at to call an API Controller in Angular showed this way.

You don't need the $.parseJSON. remove it and leave the JSON.parse intact:
var data = JSON.parse(data);
If you want to use JQuery ($) you have to import the script.
UPDATE:
if you want to redirect to an URL you can use $window:
$window.location.href = 'http://www.google.com';

Related

Angular JS: Uncaught SyntaxError: Unexpected token

I have one error in $http.json line.
Here is my code:
var myApp = angular.module('myApp', ["ionic"]);
myApp.service("Pressed", ["$http", "$log", Pressed]);
myApp.controller("AppCtrl", ["$scope", "Pressed", "$log", AppCtrl]);
function AppCtrl($scope, Pressed, $log){
$scope.refresh = function(){
Pressed.getBlogs();
}
}
function Pressed($http, $log) {
this.getBlogs = function() {
$http.jsonp('http://oasisgroups.com/oApp/product.php?callback=JSON_CALLBACK()')
.success(function(result){
$log.info(JSON.stringify(result.product));
});
};
}
When I click on refresh button, an error is displayed in the console:
You can also here find the respective service.
I believe the main issue is that the service doesn't seem to support a jsonp call. No matter how I call the service you provided it only responds with standard JSON results and not with the JSON wrapped in the callback function. Your screen shot of Chrome even shows the raw JSON, not JSONP response from the service. If a service doesn't support JSONP you can't force it to, that is something each service does on a case by case basis depending on how it is written. So the root cause of your error is that AngularJS is expecting the callback function to be part of the response, it cannot find it, and you get the error you are seeing.
I have constructed a jasmine test for your code and it passes. That is the best I can do to confirm that your code is correct and the issue is outside of your Angular code.
Unless the web service actually responds with the expected callback function wrapping the JSON, you need to switch to a standard $http.get() and deal with any potential XSS issues that you might encounter in a different way.
You can see a working JSONP example with this url. You will note that it starts with "getdata" and then wraps the JSON content inside that function's (). Your service is not doing that with the callback query string attribute.
var myApp = angular.module('myApp', []);
myApp.controller("AppCtrl", ["$scope", "Pressed", "$log", function ($scope, Pressed, $log) {
$scope.refresh = function () {
Pressed.getBlogs($scope);
}
}]);
myApp.service('Pressed', ['$http', '$log', function ($http, $log) {
var pressed = {};
pressed.getBlogs = function ($scope) {
$http.jsonp('http://oasisgroups.com/oApp/product.php?callback=JSON_CALLBACK')
.success(function (data,status,headers,config) {
$log.info(JSON.stringify(data));
$scope.products = data.product;
console.log('Found ' + data.product.length + ' products');
})
.error(function () {
console.log("Error during http get request.");
});
};
return pressed;
}]);
Then the test would look something like this:
describe('bad_jsonp', function () {
var service, scope;
beforeEach(module('myApp'));
beforeEach(angular.mock.inject(function ($rootScope) {
scope = $rootScope.$new();
}));
beforeEach(inject(function($httpBackend, _Pressed_) {
backend = $httpBackend;
service = _Pressed_;
}));
it('test that service response contains the attribute product', function () {
backend.expect("JSONP","http://oasisgroups.com/oApp/product.php?callback=JSON_CALLBACK").
respond(200,
{"success":1,"msg":"success","product":[{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/160112WP_20160112_17_57_49_Pro__1452604019_113.193.193.146.jpg","title":"Shreenath Ji"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/1601124e199090-c030-4f01-be11-c5140cf20273__1452603831_113.193.193.146.jpg","title":"Acrylic Jali"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/1601128a718e95-7df0-4189-876e-204b715cf90d__1452603868_113.193.193.146.jpg","title":"Acrylic Jali"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/16011229b095c9-b897-4942-831f-92073f527374__1452603895_113.193.193.146.jpg","title":"Wooden Decorative"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/16011255ce3155-3956-4cfb-8dd5-39021713d350__1452603914_113.193.193.146.jpg","title":"Acrylic Jali Oranage"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/160112WP_20160112_17_33_11_Pro__1452603994_113.193.193.146.jpg","title":"Acrylic Jali Green"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/160112607c733c-8dd5-442c-a584-6179339abb0e__1452603974_113.193.193.146.jpg","title":"Acrylic Jali White"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/160112300cca44-e783-48f7-b035-59ef0529ad53__1452603956_113.193.193.146.jpg","title":"Wooden Decorative"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/16011279e7c001-6663-4dfe-91ce-70cc87e6ca2d__1452603940_113.193.193.146.jpg","title":"Wooden Decorative"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/160112WP_20160112_17_58_35_Pro__1452604069_113.193.193.146.jpg","title":"Corian Design "},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/160112WP_20160112_17_59_14_Pro__1452604098_113.193.193.146.jpg","title":"Corian Design "},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/160112WP_20160112_18_00_34_Pro__1452604138_113.193.193.146.jpg","title":"AalaBuster"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/160112WP_20160112_18_01_20_Pro__1452604320_113.193.193.146.jpg","title":"AalaBuster"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/160112WP_20160112_18_02_08_Pro__1452604343_113.193.193.146.jpg","title":"Corian wash basin"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/160112WP_20160112_18_02_25_Pro__1452604370_113.193.193.146.jpg","title":"3d Corian Design"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/160112WP_20160112_18_02_43_Pro__1452604393_113.193.193.146.jpg","title":"3d Corian Design"},{"image":"http:\/\/oasisgroups.com\/images\/oacgallery\/160112WP_20160112_18_03_13_Pro__1452604424_113.193.193.146.jpg","title":"3d Wooden Decorative"}]}
);
expect(service).toBeDefined();
service.getBlogs(scope);
backend.flush();
console.log(scope.products);
var products = scope.products;
expect(products.length).toBe(17);
expect(products[0].title).toBe("Shreenath Ji");
});
});
The test doesn't include the actual callback in the response content because the mocking framework handles that wrapping and unwrapping for you just like AngularJS does in the first place, so it isn't an exact test but it is as close as I can get with what we have.

Angular JS custom service success callback not working

Trying out a basic example of Angular JS.
Created a index.html file and including the main.html file - controller MainController and using the service - service1.
The data grid population is written in the success callback (onCallComplete) of the service1, which is not called for some reason.
Neither its showing any error.
Where am I going wrong?
Link to my code
change your onCallComplete from
var onCallComplete = function(data) {
$scope.user = data;
service1.getRepos($scope.user).then(onReposComplete, onError);
};
to
function onCallComplete(data) {
console.log(data);
$scope.user = data;
service1.getRepos($scope.user).then(onReposComplete, onError);
}
Here is the working plunker
or move your service1.getUser($scope.username).then(onCallComplete,onError); beneath onCallComplete like given below.
var onCallComplete = function(data) {
$scope.user = data;
service1.getRepos($scope.user).then(onReposComplete, onError);
};
service1.getUser($scope.username).then(onCallComplete,onError);
The Reason is When you define your function as var onCallComplete =function(data) the function definition happens at runtime. but using function onCallComplete(data) the function gets defined while parsing the script.So it would be available at any point during runtime.

Angular How to properly use a factory returned data

I have a factory use $resource to make HTTP calls.
The factory code:
.factory('me', function($resource, API_URL) {
var url = API_URL + 'api/me';
return $resource(url);
})
I use it in a controller and I manage to display the data returned from factory in view like this:
.controller('AppCtrl', function($scope, me) {
$scope.data = me.get();
console.log($scope.data);
})
View code to display this data was obiously like this:
<h3>{{data.displayName}}</h3>
when I took a look at my console I found that am getting the data but I also getting $promise and $resolved I had a feeling that am not doing it the way it meant to be and I made sure when I tried to use the same factory in different controller like this:
.controller('newItemCtrl', function($scope, me) {
var data = me.get();
console.log(data.displayName);
})
I got undefined.
My question again how it work in the first use and didn't in the second use.
$resource.get() does not immediately return data. Instead it returns an empty reference that is updated with the data once the data is returned from the server.
Instead of directly assigning the result of the get() to your scope variable, you should be using the success and error callbacks:
angular.module('foo').controller('AppCtrl', function($scope, me) {
me.get(function (result) {
$scope.data = result;
console.log($scope.data);
}, function (error) {
// handle error here
});
});
It returns a promise, so you should use like that:
.controller('AppCtrl', function($scope, me) {
$scope.data = me.get(function(data) {
$scope.data = data;
console.log($scope.data);
})
})
https://docs.angularjs.org/api/ngResource/service/$resource

Can not figure out how to store $rootScope in angular.bootstrap

I'm trying to call a web service in AngularJS bootstrap method such that when my controller is finally executed, it has the necessary information to bring up the correct page. The problem with the code below is that of course $rootScope is not defined in my $http.post(..).then(...
My response is coming back with the data I want and the MultiHome Controller would work if $rootScope were set at the point. How can I access $rootScope in my angular document ready method or is there a better way to do this?
angular.module('baseApp')
.controller('MultihomeController', MultihomeController);
function MultihomeController($state, $rootScope) {
if ($rootScope.codeCampType === 'svcc') {
$state.transitionTo('svcc.home');
} else if ($rootScope.codeCampType === 'conf') {
$state.transitionTo('conf.home');
} else if ($rootScope.codeCampType === 'angu') {
$state.transitionTo('angu.home');
}
}
MultihomeController.$inject = ['$state', '$rootScope'];
angular.element(document).ready(function () {
var initInjector = angular.injector(["ng"]);
var $http = initInjector.get("$http");
$http.post('/rpc/Account/IsLoggedIn').then(function (response) {
$rootScope.codeCampType = response.data
angular.bootstrap(document, ['baseApp']);
}, function (errorResponse) {
// Handle error case
});
});
$scope (and $rootScope for that matter) is suppose to act as the glue between your controllers and views. I wouldn't use it to store application type information such as user, identity or security. For that I'd use the constant method or a factory (if you need to encapsulate more logic).
Example using constant:
var app = angular.module('myApp',[]);
app.controller('MainCtrl', ['$scope','user',
function ($scope, user) {
$scope.user = user;
}]);
angular.element(document).ready(function () {
var user = {};
user.codeCampType = "svcc";
app.constant('user', user);
angular.bootstrap(document, ['myApp']);
});
Note Because we're bootstrapping the app, you'll need to get rid of the ng-app directive on your view.
Here's a working fiddle
You could set it in a run() block that will get executed during bootstrapping:
baseApp.run(function($rootScope) {
$rootScope.codeCampType = response.data;
});
angular.bootstrap(document, ['baseApp']);
I don't think you can use the injector because the scope isn't created before bootstrapping. A config() block might work as well that would let you inject the data where you needed it.

Angular - how do I use $resource

I have this controller that is working correctly for an Angular UI typeahead. How would I add the server call as a resource?
var receivableApp = angular.module('receivableApp', ['ui.bootstrap', 'ngResource'])
.controller('ReceivableController', function ($scope,$http) {
$scope.Debtors = function (term) {
return $http.get('/Receivable/GetDebtors/?term=' + term).then(function (response) {
return response.data;
});
};
});
receivableApp.factory('GetDebtors', ['$resource',
function($resource){
return $resource('/Receivable/GetDebtors/');
}]);
This will add a service GetDebtors with a default GET, and other REST handlers.
Now, to make a call inside your controller, you can do:
debtControllers.controller('DebtCtrl', ['$scope', 'GetDebtors',
$scope.debts = GetDebtors.get({term: 'foo'});
]);
This is equivalent to making a call to /Receivable/GetDebtors/?term=foo.
If you want to change the behavior, you can override the default methods available on $resource. More details can be found here.
$resource was meant to retrieve data from an endpoint, manipulate it and send it back.
It's fine to have custom methods on your resource, but you don't want to miss out on the cool features it comes with OOTB.var Todo = $resource('/api/1/todo/:id');
//create a todo var todo1 = new Todo();
todo1.foo = 'bar';
todo1.something = 123;
todo1.$save();

Resources