I start with angularJS and I don't understant how you can push a variable from the controller to a service.
I try with $rootScope but the value of the variable was undefined
here is my service :
technoServices.factory('Config',['$rootScope','$resource',
function($rootScope,$resource,token){
return $resource('../../rest/config',null,{
get: {
method:'GET',
headers:{'X-Token':""+$rootScope.headers},
isArray:false}
});
}]);
and here is my controller :
var technoControllers = angular.module('technoControllers', []);
technoControllers.controller('loginCtrl', ['$scope','$rootScope', 'Techno',function($scope,$rootScope, Techno) {
$scope.getXtoken = function (user,psw){
$scope.config = Techno.post({username:user,password:psw},function(response,headers){
$scope.status= response.status;
$rootScope.headers = headers('X-Token');
if($rootScope.headers != null){
$scope.log = true;
}else{
$scope.log = false;
}
})};
}
]);
technoControllers.controller('configCtrl', ['$scope', 'Config', function($scope, Config) {
$scope.getConfig = function (){
$scope.maConfig = Config.get();
}
So as you can see , I need the variable from the response header of my first service in the header request of my seconde service. How can I do it ?
You can just use another service as shared service which will have the value and inject in both the controller and service.
Code snippet would be like this.
technoServices.factory('Shared',
function(){
var Shared={};
Shared.setValue=function(header){
Shared.header = header;
}
Shared.getValue=function(){
return Shared.header;
}
return Shared;
});
And in controller you can use as
technoControllers.controller('loginCtrl', ['$scope','$rootScope', 'Techno',function($scope,$rootScope, Techno, Shared) {
$scope.getXtoken = function (user,psw){
$scope.config = Techno.post({username:user,password:psw},function(response,headers){
$scope.status= response.status;
Shared.setValue(headers('X-Token'));
//$rootScope.headers = headers('X-Token');
if($rootScope.headers != null){
$scope.log = true;
}else{
$scope.log = false;
}
})};
}
]);
You can inject Shared service in Config to get data
technoServices.factory('Config',['$rootScope','$resource','Shared'
function($rootScope,$resource,token,Shared){
return $resource('../../rest/config',null,{
get: {
method:'GET',
//headers:{'X-Token':""+$rootScope.headers},
headers:{'X-Token':""+Shared.getValue()},
isArray:false}
});
}]);
Related
Im using angularjs in MVC.
Here My Controller.js:
//Get User By ID
$scope.GetUserById = function (UID) {
var Get = UserService.GetUserById(UID);
Get.then(function (response) {
$scope.User = response.data;
alert($scope.User.Address);
});
};
services.js:
//Get By ID
this.GetUserById = function (UID) {
debugger;
return $http.get("../api/UsersData/GetUserById?UID=" + UID);
};
When I'm using the debugger, the alert message is displayed. If I'm not debugging then it doesn't return a value.
What is the issue in my code?
How to display the value to html page?
You should get it working with few adjustments.
Service.js:
angular.module('myApp').factory('MyService', MyService);
//Avoid Minification Problems
MyService.$inject = [ '$http' ];
function MyService( $http ){
function GetUserById(UID){
return $http.get('../api/UsersData/GetUserById?UID=' + UID)
.then( function (response) {
if(response){
return response;
}
});
}
//Expose Method to External Calls
return {
GetUserById : GetUserById
}
}
Controller.js:
angular.module('myApp').controller('MyController', MyController);
MyController.$inject = [ '$scope', 'MyService' ];
function MyController( $scope, MyService ){
$scope.GetUserById = function(UID){
MyService.GetUserById(UID).then( function(response){
$scope.User = response.data;
alert($scope.User.Address);
});
}
}
Make sure what response is actually returning with a $log or using console.log in order to properly alert the address. Do this check also in the service, for instance you should check if response.address exists.
You can also use a Service instead of a Factory.
I am trying to test a controller. The controller uses a service which is using $http to get the data from a json file (This json file is just a mock up of response returned from server)
My problem is that when I am testing the controller, it creates the controller object and even calls the service. But it doesnt call the $http mocked response. I not sure where I am going wrong. I tried looking at few examples but all of them are using $q.
My service looks like this:
(function(){
angular.module('mymodule')
.factory('MyService', MyService);
MyService.$inject = ['$http'];
function MyService($http) {
var service = {
retrieveData : retrieveData
};
return service;
function retrieveData(containerLabel){
var myGrossData = [];
var isMatchFound = false;
var myindex = containerLabel.slice(-4);
return $http.get('app/myGrossData.json').then(function(response) {
console.log('inside http retrieveData: ');
myGrossData = response.data;
var myindexExists = false;
var mydataObject = [];
var defaultdata = [];
angular.forEach(myGrossData, function (myGrossData) {
if (myindex === myGrossData.myindex) {
mydataObject = myGrossData;
isMatchFound = true;
}
if(!isMatchFound && myGrossData.myindex === '2006')
{
mydataObject = myGrossData;
}
if(myGrossData.myindex === '2006'){
defaultdata = myGrossData;
}
});
if (isMatchFound && response.status === 200)
{
return mydataObject;
}
else if(!isMatchFound && (response.status === 200 || response.status === 201)){
return defaultdata;
}
else //all other responses for success block
{
return 'Incorrect Response status: '+response.status;
}
},
function(error){
return 'Error Response: '+error.status;
}
);
}
};
})();
The controller calling it is :
(function () {
'use strict';
angular
.module('mymodule', [])
.controller('MyCtrl', MyCtrl);
MyCtrl.$inject = ['$scope', 'MyService'];
function MyCtrl($scope, MyService) {
var vm = this;
vm.datafromsomewhere = datafromsomewhere;
vm.displayData = [];
vm.disableBarCode = false;
vm.childCount = 0;
vm.headertext="Master Container Builder";
init();
function init() {
console.log('MyCtrl has been initialized!');
console.log(vm.headertext);
}
function myfunctionCalledByUI(input) {
processData(input);
}
function processData(containerLabel){
MyService.retrieveMasterContainer(containerLabel).then(function(data){
vm.displayData = data;
});
vm.disableBarCode = true;
vm.childCount = (vm.displayData.childData === undefined) ? 0: vm.displayData.childData.length;
vm.headertext="Myindex "+vm.displayData.myindex;
if ( vm.displayData.masterDataId.match(/[a-z]/i)) {
// Validation passed
vm.displayData.masterDataId ="No Shipping Label Assigned";
}
else
console.log('else: '+vm.displayData.masterDataId);
console.log('length of childData: '+vm.childCount);
}
}
})();
and finally my spec looks like this:
var expect = chai.expect;
describe('Test Controller', function () {
var rootScope, compile; MyService = {};
var $scope, $controller;
beforeEach(module('ui.router'));
beforeEach(function() {
module('mymodule');
inject(function ($rootScope, _$compile_,_$controller_) {
rootScope = $rootScope;
compile = _$compile_;
$scope = $rootScope.$new();
MyService = jasmine.createSpyObj('MyService', [
'retrieveData'
]);
$controller = _$controller_('MyCtrl', {
$scope: $scope
});
});
});
it('controller should be initialized and data should also be initialized', function() {
expect($controller).to.not.be.undefined;
expect($controller).to.not.be.null;
expect($controller.disableBarCode).to.equal(false);
expect($controller.childCount).to.equal(0);
expect($controller.headertext).to.equal("Master Container Builder");
});
it(' should process data when containerLabel is called into myfunction', function() {
$controller.handKeyed('12001');
expect(MyService.retrieveData).to.have.been.called;
expect($controller.processData).to.have.been.called;
expect($controller.disableBarCode).to.equal(true);
expect($controller.childCount).to.equal(0);
expect($controller.headertext).to.equal("Master Container Builder");
});
});
I am using following techstack if it helps:
angular 1.5
Ionic
Karma-jasmine
The code works when I run it. My issue is that when i run the test it doesnt populate the data in my vm.displayData variable. how do I make it get some data into the service. I added in some log statements and it skips it completely.
After all the test run including unrelated tests to this one, then I see the log statements from MyService. I am not sure how to approach this.
I think what you are looking for is the $httpBackend service. It will mock the request indicating the result. So, when your service hit the url, it will return what you passed to the $httpBackend configuration.
A simple example would be:
it('should list newest by category', function(){
$httpBackend
.expectGET(url)
.respond(techPosts /*YOUR MOCKED DATA*/);
$stateParams.category = 'tech';
var controller = $controller('HomeCtrl', { PostsResource: PostsResource, $stateParams: $stateParams });
controller.listNewestPosts();
$httpBackend.flush();
expect(controller.posts).toEqual(techPosts.posts);
});
This is an ASP.NET MVC app with AngularJS.
When the application loads, we have to call some action method which returns a dictionary of resources, string key string value.
This array/dictionary of resources, needs to be available throughout the application.
How can we wait until these resources are loaded before accessing them within the application?
var app = angular.module("app", []);
app.controller("TestCtrl", ['cacheService', function (cacheService) {
var self = this;
self.test = function () {
var value = cacheService.getResourceValue('Err_lbl_UserExist');
}
}]);
app.factory('cacheService', ['$http', function ($http) {
var obj = {};
obj.resourceDictionary = [];
obj.loadResourceDictionary = function () {
var httpConfig = {
url: "/Cache/GetResourceDictionary",
method: "GET",
headers: {
"X-Requested-With": 'XMLHttpRequest',
"__RequestVerificationToken": $("[name=__RequestVerificationToken]").val()
}
}
$http(httpConfig)
.success(function (data) {
obj.resourceDictionary = data;
});
}
obj.getResourceValue = function (resourceKeyName) {
if (obj.resourceDictionary.length <= 0) {
obj.loadResourceDictionary();
}
return obj.resourceDictionary[resourceKeyName];
}
return obj;
}]);
EDIT w/ Accepted Answer
var app = angular.module("app", []);
app.controller("TestCtrl", ['cacheService', function (cacheService) {
var self = this;
self.test = function () {
var value = cacheService.getResourceValue('Err_lbl_UserExist');
}
}]);
app.factory('cacheService', ['$rootScope', '$http', function ($rootScope, $http, $q) {
var obj = { resourcesLoaded: false };
obj.loadResourceDictionary = function () {
obj.resourcesLoaded = false;
var httpConfig = {
url: "Cache/GetResourceDictionary",
method: "GET",
headers: {
"X-Requested-With": 'XMLHttpRequest',
"__RequestVerificationToken": $("[name=__RequestVerificationToken]").val()
}
}
$http(httpConfig).success(function (data) {
obj.resourceDictionary = data;
obj.resourcesLoaded = true;
$rootScope.$broadcast("ResourcesLoaded", null);
});
}
obj.getResourceValue = function (resourceKeyName) {
if (!obj.resourcesLoaded) {
obj.loadResourceDictionary();
$rootScope.$on("ResourcesLoaded", function () {
return obj.resourceDictionary[resourceKeyName];
});
} else {
return obj.resourceDictionary[resourceKeyName];
}
}
return obj;
}]);
you could use broadcast and on for that.
So once your keys are loaded you fire an event using broadcast
https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$broadcast
you listen for that message wherever you need to using on :
https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on
you can store the data in a service, this will make it a singleton and you can reuse it, all you have to do is inject the service in whatever controller you need.
I'm new in angularjs and i have a problem trying to use $scope inside a $http.
inside $http i can see data but outside service i get null.
Console.log($scope.data) inside service I get data:
Console.log($scope.data) outside always null:
mycode :
(function (app, ng) {
'use strict';
app.controller('mainController', ['$scope', 'ServicePatient', function ($scope, ServicePatient) {
$scope.data = null;
ServicePatient.all().success(function (data) {
$scope.data = data;
});
$scope.sortType = 'last_Name'; // the default sort type
$scope.sortReverse = false; // the default sort order
$scope.search = ''; // the default search/filter term
$scope.filterEnabled = '';
$scope.setEnabled = function(status){
$scope.filterEnabled = status;
if(status){
angular.element(document.querySelector( '#enabledFalse')).removeClass('active-btn');
angular.element(document.querySelector( '#enabledTrue')).addClass('active-btn');
} else {
angular.element(document.querySelector( '#enabledTrue')).removeClass('active-btn');
angular.element(document.querySelector( '#enabledFalse')).addClass('active-btn');
}
}
console.log($scope.data);
}]);
app.service('ServicePatient', ['$http', function ($http) {
function all() {
return $http({
url: 'http://54.165.192.65/ekare/ws6.php?request=patient',
method: 'GET'
});
}
return {
all: all
}
}]);
}(angular.module('app', []), angular));
My Grails application doesn't receiving data from angularjs post request.
My AngularJS Controller is:
module.controller('MemberCtrl', ['$scope', '$http',
function ($scope, $http) {
$scope.submitForm = function () {
$http.post(uri + "receiveNewMember", $scope.member)
.success(function (data) {
console.log("Data Sent With Success! " + data);
})
.error(function (data) {
console.log("Fail");
});
};
}]);
My Grails Action is:
def receiveNewMember(){
render text: params.name
}
The Debugger Stops into action. But params variable hasn't any data but controller and action.
Someone knows how can I fix this?
The Post Data can be accessed via request.JSON in Grails Controller.
You can do something like this to emulate the way grails works:
post query parameters like jQuery
Also I created a Serializer factory to serialize any kind of javascript object to the expected way on grails:
(function() {
'use strict';
angular.module('app').factory('Serializer', function ($filter) {
function SerializerService(){}
var serializerService = new SerializerService();
serializerService.excludedProperties = ['$$hashKey'];
SerializerService.prototype.serialize = function(object){
var results = {};
this.serializeObject(results, object, "");
return results;
};
SerializerService.prototype.serializeObject = function(results, object, nameAtTheMoment){
if($.isArray(object)){
var array = object;
for (var i=0; i<object.length; i++){
var newNameAtTheMoment = nameAtTheMoment + "[" + i.toString() + "]";
this.serializeObject(results, array[i], newNameAtTheMoment)
}
}
else{
if(Object.prototype.toString.call( object ) === "[object Object]"){
var i=0;
for(var property in object){
if (object.hasOwnProperty(property) && this.excludedProperties.indexOf(property) == -1) {
var newNameAtTheMoment;
if(nameAtTheMoment !== "")
newNameAtTheMoment = nameAtTheMoment + "." + property;
else
newNameAtTheMoment = property;
this.serializeObject(results, object[property], newNameAtTheMoment);
i++;
}
}
}
else{ //the object is a simple value
if(Object.prototype.toString.call(object) === '[object Date]'){
var dateServerFormat = window.appConfig.dateServerFormat;
results[nameAtTheMoment] = $filter('date')(object, dateServerFormat);
}
else
results[nameAtTheMoment] = object;
}
}
};
return serializerService;
});
})();
And following the first link description you can do something like this:
angular.module('app', [...])
.config(function ($provide, $httpProvider) {
var serializer;
// Trick to inject dependencies on the config function.
$provide.factory('FactoryInjector', function () {
return {
setSerializer: function(serializerParam){
serializer = serializerParam;
}
};
});
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
$httpProvider.defaults.transformRequest = [function(data) {
return angular.isObject(data) && String(data) !== '[object File]' ? $.param(serializer.serialize(data)) : data;
}];
})
.run(function ($rootScope, $state, $stateParams, Serializer, FactoryInjector) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
FactoryInjector.setSerializer(Serializer);
});