I have a new userContext.js file which attempts to create a new service entitle "userService". This service in turn will communicate with the server and return some environmental settings, as well as a user session ID.
This all works fine when I call it from my dashboard.js into my datacontext.js controller; however I would like to actually create a service for this. I would then persist those session vars throughout the lifetime of each user session.
In my initial attempt to create the service I am getting lots of injector errors, for example :
Error: [ng:areq] Argument 'fn' is not a function, got string
I have included it in my index.html:
<script src="app/services/userContext.js"></script>
Here's a dashboard controller snippet where I attempt to inject 'userService' :
(function () {
'use strict';
var controllerId = 'dashboard';
angular.module('app').controller(controllerId, ['$scope', '$routeParams', '$location', 'common', 'datacontext', 'userService', dashboard]);
function dashboard($scope, $routeParams, $location, common, datacontext, userService) {
var getLogFn = common.logger.getLogFn;
var log = getLogFn(controllerId);
var vm = this;
getRzInitParams();
function getRzInitParams() {
log('Initializing Server Connection...');
var rzParams = "";
datacontext.getRzInitParams().then(function (data) {
rzParams = data;
initRz(data);
});
}
function initRz(data) {
var response;
datacontext.initRz().then(function (data) {
response = data[0].split(":")
if (response[1].match(/SUCCESS/g)) {
log('Server init returned ' + response[1].match(/SUCCESS/g));
openUserSession();
}
else {
log('Server init failed !');
}
});
}
}
})();
and here's a snippet from datacontext.js :
(function () {
'use strict';
var serviceId = 'datacontext';
angular.module('app').factory(serviceId, ['$http', 'common', datacontext]);
function datacontext($http, common) {
var $q = common.$q;
var service = {
initRz: initRz,
openUserSession: openUserSession,
getRzInitParams: getRzInitParams
};
return service;
function initRz() {
domain = "localhost:"
port = "49479";
controllerpath = "/api/init";
space = "rz64698";
env = "rz64698";
cl_config = "C:\\Rz\\rz64698\\master\\bin\\cl_config.xml";
var url = "http://" + domain + port + controllerpath + "?space=" + space + "&environment=" + env + "&clConfig=" + cl_config;
var deferred = $q.defer();
deferred.notify("Getting init parameters...");
var retval = [];
$http({
method: 'GET',
encoding: 'JSON',
headers: {
'Access-Control-Allow-Origin': 'true'
},
withCredentials: true,
url: url
}).success(function (data, status, headers, config) {
retval = data;
deferred.resolve(retval);
});
return deferred.promise;
}
function getRzInitParams() {
var deferred = $q.defer();
var retval = [];
$http({
method: 'GET',
encoding: 'JSON',
url: 'breeze/breeze/GetRzEnv'
}).success(function (data, status, headers, config) {
retval = data;
deferred.resolve(retval);
});
return deferred.promise;
}
}
})();
and finally the new 'userService' service I am now creating :
(function () {
'use strict';
var app = angular.module('app');
app.service('userService', '$http', function () {
// define private vars
var _rzEnvParams = [];
var _sessionID = '';
this.initrz = function(domain, port, controllerpath, space, env, clariteconfig) {
domain = "localhost:"
port = "49479";
controllerpath = "/api/init";
space = "rz64698";
env = "rz64698";
cl_config = "C:\\rz\\rz64698\\master\\bin\\clarite_config.xml";
var url = "http://" + domain + port + controllerpath + "?space=" + space + "&environment=" + env + "&clariteConfig=" + cl_config;
var deferred = $q.defer();
deferred.notify("Getting Rage init parameters...");
var retval = [];
$http({
method: 'GET',
encoding: 'JSON',
headers: {
'Access-Control-Allow-Origin': 'true'
},
withCredentials: true,
url: url
}).success(function (data, status, headers, config) {
retval = data;
deferred.resolve(retval);
});
return deferred.promise;
}
this.getrzInitParams = function () {
var deferred = $q.defer();
deferred.notify("Getting Rage init parameters...");
var retval = [];
$http({
method: 'GET',
encoding: 'JSON',
url: 'breeze/Rage/GetrzEnv'
}).success(function (data, status, headers, config) {
retval = data;
deferred.resolve(retval);
});
return deferred.promise;
}
this.openUserSession = function() {
domain = "localhost:"
port = "49479";
controllerpath = "/api/open";
user = "";
pass = "";
var url = "http://" + domain + port + controllerpath + "?userid=" + user + "&pass=" + pass;
var deferred = $q.defer();
deferred.notify("Opening user session...");
var retval = [];
$http({
method: 'GET',
encoding: 'JSON',
headers: {
'Access-Control-Allow-Origin': 'true'
},
withCredentials: true,
url: url
}).success(function (data, status, headers, config) {
retval = data;
deferred.resolve(retval);
});
return deferred.promise;
}
this.closeUserSession = function(domain, port, controllerpath) {
}
});
})();
If you want to inject some service you should use one of this syntaxes
if you need only angular services
app.service('userService', function ($http) {
...
if you need custom services
app.service('myService', ['$http', 'myOtherService', function($http, myOtherService) {
...
}])
app.service('userService', '$http', function () {
should be like
app.service('userService', function ($http) {
hope this will work
Related
I'm trying to learn AngularJS and I have the following service that works, but I'm wondering if there's a better way of writing it that is simpler and involves less duplication of code. Can you think of anything?
The service:
app.service("myService", function ($http) {
this.callData1 = function () {
var url = myurl1;
function getData() {
return $http.get(url);
}
return {
getData: getData,
}
},
this.callData2 = function () {
var url = myurl2;
function getData() {
return $http.get(url);
}
return {
getData: getData,
}
},
this.callData3 = function () {
var url = myurl3;
function getData(var1, var2) {
return $http({
url: url,
method: "GET",
params: { var1: var1, var2: var2 }
});
}
return {
getData: getData,
}
}
});
My controller:
app.controller("myController", function ($scope, myService) {
myService.callData1().getData().then(function (response) {
$scope.var1 = response.data;
});
myService.callData2().getData().then(function (response) {
$scope.var2 = response.data;
});
var var1 = "something";
var var2 = "something else";
myService.callData3().getData(var1, var2).then(function (response) {
$scope.var3 = response.data;
});
});
You can generalize it as follows:
app.service("myService", function ($http) {
this.getData = function(url, method, params){
var httpParams = {
url: url,
method: method || "GET", // If method is skipped, use "GET" by default
params: params || {} // If no params are given, take {}
};
return $http.get(httpParams);
};
});
And in controller, you can use this service as follows:
app.controller("myController", function ($scope, myService) {
var url = "https://blahblah";
myService.getData(url).then(function (response) {
$scope.var1 = response.data;
});
var params = {var1: "something", var2: "something2"};
myService.getData(url, "POST", params).then(function (response) {
$scope.var1 = response.data;
});
});
I want to multiple value from from serice page to php page.I want to pass 'data','albimg','albvideo' to php page.now I caught the error as shown in image.
var deferred = $q.defer();
data.pagename = "create_album";
$http.post('js/data/album.php', {action:{"data":data,"albimg":albimg,"albvideo":albvideo}})
.success(function (data, status, headers, config)
{
console.log(status + ' - ' + action);
deferred.resolve(action);
})
.error(function (action, status, headers, config)
{
deferred.reject(action);
console.log('error');
});
return deferred.promise;
php page:
$postdata = file_get_contents("php://input",true);
$request = json_decode($postdata);
$now = date('Y-m-d H:i:s');
echo $sql="INSERT INTO `$prefix.album` (CONTENT_VALUES,CreatedTime)VALUES('$postdata','$now')";
you can do it by using param property: like this;
var data = {"data":data,"albimg":albimg,"albvideo":albvideo};
$http({ url: "js/data/album.php", method: "POST", params: data })
There is no action param defined in success callback.
Your code
.success(function (data, status, headers, config) // No Action here
{
console.log(status + ' - ' + action); // This line gives error
deferred.resolve(action);
})
Should be
.success(function (data, status, headers, config, action) // Add Action here
{
console.log(status + ' - ' + action);
deferred.resolve(action);
})
Look to this example:
function PhoneListCtrl($scope, phones) {
$scope.phones = phones;
$scope.orderProp = 'age';
}
PhoneListCtrl.resolve = {
phones: function(Phone, $q) {
var deferred = $q.defer();
deferred.reject();
Phone.query(function(successData) {
deferred.resolve(successData);
}, function(errorData) {
deferred.reject();
});
return deferred.promise;
},
delay: function($q, $defer) {
var delay = $q.defer();
$defer(delay.resolve, 1000);
return delay.promise;
}
}
I think that you forget add $defer to your function. Do you realy need asynchronously? Beacouse if you use $q it's that you need it. But if you just want to send data to php file easiest way to use something like this:
angular.module('httpExample', [])
.controller('FetchController', ['$scope', '$http', '$templateCache',
function($scope, $http, $templateCache) {
$scope.method = 'Post';
$scope.url = 'http-hello.php';
$scope.fetch = function() {
$scope.code = null;
$scope.response = null;
$http({method: $scope.method, url: $scope.url, cache: $templateCache}).
then(function(response) {
$scope.status = response.status;
$scope.data = response.data;
}, function(response) {
$scope.data = response.data || "Request failed";
$scope.status = response.status;
});
};
$scope.updateModel = function(method, url) {
$scope.method = method;
$scope.url = url;
};
}]);
I started using angular a week ago and I have been banging me head trying to solve this problem. I have a service that wraps $http because multiple controllers call the same url. There is one page that has a lot of business logic on the server on a post so I want to call $route.reload(). It seems to work because after vm.saveItem() the controller is reinitialized, but the $http.get() never sends the signal to the server for the new data. What am I doing wrong?
myModule.factory("itemRepository", function ($http) {
var baseUrl = "/api/inventory";
return {
getLocations: function (itemName) {
return $http({
url: baseUrl + "/" + itemName + "/locators",
method: "GET",
cache: false
});
},
addNewLocator: function (itemName, newLocator) {
return $http.post(baseUrl + "/" + itemName + "/locators", newLocator);
}
};
});
// itemEditorController.js
(function () {
"use strict";
angular.module("app-inventoryitems")
.controller("itemEditorController", itemEditorController);
function itemEditorController($routeParams, $route, itemRepository) {
// initialize vars
var vm = this;
vm.itemName = $routeParams.itemName;
vm.errorMessage = "";
// Models
vm.items = [];
vm.isBusy = true;
vm.newLocator = {};
vm.newLocator.name = vm.itemName;
// PROBLEM HERE, does not call server after post new data
// and $route.reload() was called
itemRepository
.getLocations(vm.itemName)
.then(function (response) {
angular.copy(response.data, vm.items);
}, function (err) {
vm.errorMessage = "Failed to load batches.";
})
.finally(function () {
vm.isBusy = false;
});
vm.saveItem = function () {
vm.isBusy = true;
itemRepository.addNewLocator(vm.itemName, vm.newLocator)
.then(function (response) {
vm.newLocator = {};
$route.reload();
}, function (error) {
vm.errorMessage = "Failed to save new item.";
})
.finally(function () {
vm.isBusy = false;
})
}
}
})();
Try to add dynamic parameter to your request:
$http({
url: baseUrl + "/" + itemName + "/locators",
method: "GET",
cache: false,
params: {
r: Math.random().toString(16).substr(2)
}
});
If issue was solved, need looking for HTTP Caching policies.
Google for necessary server-side headers.
I have a JSON source and want to get results from it with a post request.
When I test with POSTMAN extension in chorme it works really well. But when I do that with angularJS the page keep loading and chrome consoles shows errors.
My code is here:
angular.module('loginApp', []).controller('loginController', function ($scope, $http) {
$scope.userName = '';
$scope.userPass = '';
$scope.output = function () {
var params = JSON.stringify({
username: '******',
password: '******'
});
$http({url: "http://xx.xx.xx.xx/api/user/login.json",
method: 'POST',
data: params,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
}).then(function (response) {
return response;
});
};
});
Any help would be appreciated :)
try this, and after post error if occured:
var LoginApp = angular.module('loginApp', []);
LoginApp.controller('loginController', function ($scope, $common) {
$scope.userName = '';
$scope.userPass = '';
$scope.output = function () {
var params = JSON.stringify({
username: '******',
password: '******'
});
$common.ajax("http://xx.xx.xx.xx/api/user/login.json", params, "POST").then(function (response) {
console.log(response);
return response;
});
};
});
LoginApp.factory("$common", function($http, $q) {
function ajax(url, param, method) {
var request = $http({
method: method,
url: url,
data:param
});
var promise = request.then(
function(response) {
return(response.data);
},
function(response) {
console.log("Ocurred error: " + response);
return($q.reject("Something went wrong"));
}
);
return promise;
}
return({
ajax:ajax
});
});
Try this:
$scope.output = function () {
var params = {
username: '******',
password: '******'
};
$http.post("http://xx.xx.xx.xx/api/user/login.json", params)
.then(function (response) {
return response;
});
};
Also you should move your http request to a service. It's a bad practice put it in a controller.
How do I return "stories" by issuing "vm.stories = storyDataAsFactory.stories" vs. what I do now, which is "vm.stories = storyDataAsFactory.stories()" ? I've tried every combination possible without success. Furthemore, I'm able to call storyDataAsFactory.getStories without the parenthesis, which makes sense based on how I have it configured, but when I create a function that returns self.stories it doesn't work.
The below code works as specified -
storyDataAsFactory.$inject = ['$http', '$q'];
angular.module('ccsApp').factory('storyDataAsFactory', storyDataAsFactory);
function storyDataAsFactory($http, $q) {
var self = this;
var stories = [];
function getStories(url) {
url = url || '';
var deferred = $q.defer();
$http({method: 'GET', url: url})
.success(function (data, status, headers, config) {
self.stories = data;
deferred.resolve(data);
})
.error(function (data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
}
function listStories() {
return self.stories;
}
return {
stories: listStories,
getStories: getStories('stories.json')
};
}
UPDATE:
I'm still having problems. Here's my exact code, which I changed per the community -
storyDataAsFactory.$inject = ['$http', '$q'];
angular.module('ccsApp').factory('storyDataAsFactory', storyDataAsFactory);
function storyDataAsFactory($http, $q) {
var stories = [];
function getStories(url) {
url = url || '';
if (url !== '') {
var deferred = $q.defer();
//determine if ajax call already occurred;
//if so, data exists in cache as local var
if (stories.length !== 0) {
deferred.resolve();
return deferred.promise;
}
$http({method:'GET', url:url})
.success(function (data, status, headers, config) {
stories = data;
deferred.resolve();
})
.error(function (data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
} else {
alert('URL was empty.');
}
}
return {
stories: stories,
getStories: function(url) {
getStories(url);
}
};
}
storyDataAsFactory.stories does not return anything. Remember, I've ensued that resolve fired appropriately so this is not an async. issue. I just don't get this! I've been at it for hours w/o success.
I think you are confused with Angular service and factory concept:
Lets dicuss below:
Angular service:
module.service( 'serviceName', function );
Result: When declaring serviceName as an injectable argument you will be provided
with the instance of a function passed to module.service.
Angular factory
module.factory( 'factoryName', function );
Result: When declaring factoryName as an injectable argument you will be provided
the value that is returned by invoking the function reference passed to
module.factory. So if you want to access the methods of that factory then
they should be there along with returned value.
Angular's service version of your given code will be:
schoolCtrl.service('storyDataAsService', storyDataAsService);
function storyDataAsService($http, $q) {
var self = this;
var stories = [];
this.getStories = function(url) {
url = url || '';
var deferred = $q.defer();
$http({method: 'GET', url: url})
.success(function (data, status, headers, config) {
self.stories = data;
deferred.resolve(data);
})
.error(function (data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
};
this.stories = function(){
// #TODO return value
}
}
Angular's factory version:
storyDataAsFactory.$inject = ['$http', '$q'];
angular.module('ccsApp').factory('storyDataAsFactory', storyDataAsFactory);
function storyDataAsFactory($http, $q) {
var self = this;
var stories = [];
function getStories(url) {
url = url || '';
var deferred = $q.defer();
$http({method: 'GET', url: url})
.success(function (data, status, headers, config) {
self.stories = data;
deferred.resolve(data);
})
.error(function (data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
}
return {
stories: function() {
// #TODO return value
},
getStories: getStories
};
}
In your case self is provider of your factory storyDataAsFactoryProvider. But you need use local variable stroies, not provider object field self.stroies. I have fixed your bugs. Now it works.
UPD: if you want to use stories as field instead of getter you cannot change local variable (reference to original array). You may modify original array only.
storyDataAsFactory.$inject = ['$http', '$q'];
angular.module('ccsApp', /*XXX added []*/[]).factory('storyDataAsFactory', storyDataAsFactory);
function storyDataAsFactory($http, $q) {
var stories = [];
function getStories(url) {
url = url || '';
if (url !== '') {
var deferred = $q.defer();
//determine if ajax call already occurred;
//if so, data exists in cache as local var
if (stories.length !== 0) {
deferred.resolve();
return deferred.promise;
}
$http({method:'GET', url:url})
.success(function (data, status, headers, config) {
// XXX using this code you lose original array
//stories = data;
// XXX instead you need to clear and to fill original array
stories.splice(0, stories.length);
data.forEach(function(x) { stories.push(x); });
deferred.resolve();
})
.error(function (data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
} else {
alert('URL was empty.');
}
}
return {
stories: stories, // XXX using field instead of getter you need to keep original array
getStories: function(url) {
getStories(url);
}
};
}
// ------------ tests --------------------
describe('storyDataAsFactory.stories()', function() {
var $httpBackend, $http, $q, storyDataAsFactory;
beforeEach(module('ccsApp'));
beforeEach(inject(function(_$httpBackend_) {
$httpBackend = _$httpBackend_;
$httpBackend.whenGET('stories.json').respond([1, 2, 3]);
}));
beforeEach(inject(function(_$http_, _$q_, _storyDataAsFactory_) {
$http = _$http_;
$q = _$q_;
storyDataAsFactory = _storyDataAsFactory_;
}));
it('should return empty array before ajax resolved', function() {
storyDataAsFactory.getStories('stories.json');
expect(storyDataAsFactory.stories).toEqual([]);
$httpBackend.flush();
});
it('should return filled array after ajax resolved', function() {
storyDataAsFactory.getStories('stories.json');
$httpBackend.flush();
expect(storyDataAsFactory.stories).toEqual([1, 2, 3]);
});
});
// ------------ run tests --------------------
window.onload = function() {
var jasmineEnv = jasmine.getEnv();
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.execute();
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/1.3.1/jasmine.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/1.3.1/jasmine.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/1.3.1/jasmine-html.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.28/angular-mocks.js"></script>