How can I access values returned from service using controller. In my code service.js function showInfo() returns JSON objects. But I cannot access these objects outside this function. If I try to do console.log from controller.js
console.log(chartService.showInfo.new_data)
I get
error Cannot read property 'new_data' of undefined.
Same happens if I try to
console.log(chartService.showInfo)
I get undefined.
How can I access the JSON object new_data inside function showInfo from the controller?
Service.js
angular.module('myApp')
.service('chartService', function (){
return {
getUrl: function init(path) {
Tabletop.init( { key: path,
callback: showInfo,
simpleSheet: true } )
}
}
function showInfo(data, tabletop){
var new_data = JSON.stringify(data.map(function(el) {
return {
"name": el[Object.keys(el)[0]],
"y": +el[Object.keys(el)[1]]
};
}));
}
})
Controller.js
angular.module('myApp')
.controller('piechartCtrl', [ '$scope', 'chartService', function (chartService, $scope) {
console.log(chartService.showInfo.new_data)
}]);
Service
angular.module('myApp').service('chartService', function (){
return {
init: init,
showInfo: showInfo
};
function init(path) {
return Tabletop.init({
key: path,
callback: showInfo,
simpleSheet: true
});
}
function showInfo(data, tabletop){
return JSON.stringify(data.map(function(el) {
return {
"name": el[Object.keys(el)[0]],
"y": +el[Object.keys(el)[1]]
};
}));
}
});
Controller
angular.module('myApp').controller('piechartCtrl', [ '$scope', 'chartService', function (chartService, $scope) {
var tabletop = chartService.init(),
chartInfo = chartService.showInfo(someData, tabletop);
console.log(chartInfo);
}]);
I don't know exactly what you wanted with the parameters in showInfo but this should get you a good way in the right direction.
Best way is with Promise.
In angular you have the q framework as $q service $q docs
Service
angular.module('myApp')
.service('chartService', function($q) {
var deferredSpreadsheet = $q.defer();
return {
getSpreadsheet: function init(path) {
Tabletop.init({
key: path,
callback: showInfo,
simpleSheet: true
});
return deferredSpreadsheet.promise;
},
}
function showInfo(data, tabletop) {
data = JSON.stringify(data.map(function(el) {
return {
"name": el[Object.keys(el)[0]],
"y": el[Object.keys(el)[1]]
};
}));
deferredSpreadsheet.resolve(data);
}
})
Controller
angular.module('myApp')
.controller('piechartCtrl', ['$scope', 'chartService', function($scope, chartService) {
var path = "https://docs.google.com/spreadsheet/pub?hl=en_US&hl=en_US&key=0AmYzu_s7QHsmdDNZUzRlYldnWTZCLXdrMXlYQzVxSFE&output=html";
var pro = chartService.getSpreadsheet(path).then(function(data) {
console.log(data)
})
}]);
Working example here
Dirty way: You can use Broadcast and Emit
in the Service:
$rootScope.$broadcast('myEvent', JSONSTUFF);
in the Controller:
$scope.$on("myEvent", function(e, json){
console.log(json);
});
Related
I created a simple AngularJS service with .factory() called $getUser that gets data from users.json:
{
"john": {
"name": "John",
"address": "New York"
},
"bob": {
"name": "Bob",
"address": "Boston"
}
}
Now I want to use this data in mainController:
angular.module('myApp', [])
.factory('$getUser', ['$http', function($http){
var users = {};
$http.get('users.json').then(
function(response) {
users.data = response.data;
}
);
return users;
}])
.controller('mainController', ['$getUser', function($getUser){
// I can access whole $getUser object
console.log($getUser);
// but when I want to access $getUser.data it gives me 'undefined'
console.log($getUser.data);
}]);
When I want to console whole $getUser object, it works, but I am not able to access $getUser.data property. Why?
Create factory as:
app.factory('$getUser', ['$http', function($http) {
var factory = {
query: function () {
return $http.get('users.json').then(function (response) {
return response.data;
}, function (result) {
alert("Error: No data returned");
});
}
}
return factory;
}]);
So you can call it as:
$scope.data = $getUser.query()
Simple demo Fiddle
However I suggest to return promise and resolve it in controller
The common approach to load JSON is:
app.factory('Items', ['$http',
function($http) {
return {
getJson: function(url) {
var ItemsJson = $http.get(url).then(function(response) {
return response.data;
});
return ItemsJson;
}
}
}
]);
and Usage:
var jsonPromise = Items.getJson('jsonData/someJSON.json');
jsonPromise.then(function (_response) {
// ...
}, function (error) {
console.error(error);
});
try this:
angular.module('myApp', [])
.factory('$getUser', ['$http', function($http) {
var users = {};
return {
getData: function() {
return $http({
url: 'users.json',
method: 'GET'
})
}
}
}])
.controller('mainController', ['$getUser', function($getUser) {
// I can access whole $getUser object
console.log($getUser);
// but when I want to access $getUser.data it gives me 'undefined'
console.log($getUser.data);
$getUser.getData().then(function(data) {
console.log(data.data);
});
}]);
Fiddle Link
I get some data through Myservice from another Controller. I can see {{users.data}} from the view, but users.length = 0 ,and $data is empty, that means I can't access to the content of MyService in getData function.. if i replace MyService with json data like
$scope.users=[{..},{..}] it works fine
thank you ..
app.service('MyService', function() {
return data = [];
});
app.controller('tableController', function ($scope,
$filter,NgTableParams,MyService) {
$scope.users= MyService
$scope.usersTable = new NgTableParams({
page: 1,
count: 6
}, {
getData: function(params) {
params.total($scope.users.length);
$scope.da = params.sorting() ? $filter('orderBy')
($scope.users, params.orderBy()) : $scope.da;
$scope.da= params.filter() ? $filter('filter')
($scope.da, params.filter()) : $scope.users;
return $scope.da.slice((params.page() - 1) *
params.count(), params.page() * params.count());
}
}
);
});
When you get your data in the first controller you call MyService.setData(data); The service will store in its local var data and keep it there. Then in the second controller you can retrieve that data by calling MyService.getData()
app.service('MyService', function() {
var ret = {
data: [],
setData: function(inData) {
ret.data = inData;
},
getData: function() {
return ret.data;
}
};
return ret;
});
the first controller 1
app.controller('EventCtrl', ['$scope', 'EventService', 'MyService',
function ($scope, EventService , MyService) {
var baseUrl = '';
$scope.getEvents=function()
{
var apiRoute = 'http://localhost:9811/notification/notification/';
var _Event = EventService.getAll(apiRoute);
_Event.then(function (response) {
$scope.events= response.data;
MyService.data = $scope.events;
MyService.setData($scope.events);
$scope.VarCtrl1= MyService;
},
function (error) {
console.log("Error: " + error);
});
}
$scope.getEvents()
}]);
i updated the service but it doesnt work ..so i modified the first controller like this what do you think?
app.controller('EventCtrl', ['$scope', 'EventService', 'MyService',
function ($scope, EventService , MyService) {
var baseUrl = '';
$scope.getEvents=function()
{
var apiRoute =
'http://localhost:9811/notification/notification/';
var _Event = EventService.getAll(apiRoute);
_Event.then(function (response) {
var data = response.data
MyService.setData(data);
$scope.VarCtrl1= MyService;
},
function (error) {
console.log("Error: " + error);
});
}
$scope.getEvents()
}]);
Thanks for the update of the service now its better ...i can have data in $users and $data in tableController but orderBy need an array but i get this :( when i do consoleLoge($scope.users)
Object {data: Array(0), setData: function, getData: function}data:
Array(9)0: Object1: Object2: Object3: Object4: Object5: Object6:
Object7: Object8: Objectlength: 9__proto__: Array(0)getData:
function ()setData: function (inData)proto: Object
tableController.js:24
i have created the custom service like this
app.service('userService', function($http,UrlService) {
return {
init: function(callback) {
$http.get(UrlService.baseUrl +'/api/users/list').then(function(user_response) {
callback(user_response);
});
}
}
})
Inside of my project main controller i have used like this to get the angular material design modal.
$scope.replyComplaint = function(user,complaint_id) {
complaint_id=user._id;
console.log(complaint_id)
$mdDialog.show({
controller: DialogCtrl,
templateUrl: 'submodules/user_management/replydialog.html',
resolve: { complaint_id : function() {return complaint_id;} },
locals: {
users: $scope.users
},
parent: angular.element(document.body),
clickOutsideToClose: true,
})
.then(function(response) {
$scope.response = response;
console.log(response);
}, function() {
//fail
});
};
created another controller for dialog as in the angular material docs as follows
function DialogCtrl($scope, $rootScope, $mdDialog, users,complaintService, UrlService, $http) {
complaintService.init(function(complaint_response) {
$scope.complaints = complaint_response.data;
$scope.getUsers();
});
$scope.getUsers = function(complaint_id) {
console.log(complaint_id);
$scope.hide = function() {
$mdDialog.hide();
};
$scope.cancel = function() {
$mdDialog.cancel();
};
$scope.replyMail = function(complaint_id) {
console.log(complaint_id);
$http.post(UrlService.baseUrl + '/api/complaints/complaint/'+complaint_id , {
complaint: "replyText"
}, $scope)
.then(function(response) {
console.log(name);
$state.reload();
}, function(response) {
console.log(name);
});
}
}
}
Now, i need to get the user_response data in DialogController. if i put console.log('$scope.users') inside of this userservice.init function, i can get the data. but not outside of it. how to get the response data outside of the userService.init function
userService.init(function(user_response) {
$scope.users = user_response.data;
}); //this is added in DialogController
Main intension is to get the user.comlaint_id in the post request of reply mail function . that user.complaint_id is a part of the user_response
Anyone please help me. Thanks
The $http.get call returns a promise, you can just use that.
app.service('userService', function($http,UrlService) {
return {
init: function(callback) {
return $http.get(UrlService.baseUrl +'/api/users/list');
}
}
});
Controller:
function Dialog($scope,$rootScope, $mdDialog,userService,UrlService,$http) {
// console.log(userService.init());
init();
function init() {
userService.init().then(function(response) {
$scope.users = response.data;
});
}
}
This also has the advantage of easier error handling:
function Dialog($scope,$rootScope, $mdDialog,userService,UrlService,$http) {
// console.log(userService.init());
init();
function init() {
userService.init().then(function(response) {
$scope.users = response.data;
}, function(error) {
// handle error
});
}
}
You should read up on angular/javascript promises and their chaining mechanism: angular promises
Here is the solution
userService.init(function(user_response) {
$scope.users = user_response.data;
$scope.init();
});
$scope.init = function() {
You can access $scope.users here
}
Call any method instead of init() in which you require $scope.users
How can one pass values from services to controllers? I have been reading stackoverflow questions regarding this and none of the solutions seem to solve my problem. I am trying to access google spreadsheets using tabletop.js When I console.log from services I can see the values however when I try to access the spreadsheet values from controller I get the following error: chartService.getProperty is not a function
The code for getting URL of the spreadsheet works fine. With get method. Not sure what I am doing wrong here.
Controller
angular.module('myapp')
.controller('piechartCtrl', function (chartService, $scope, config) {
$scope.values = chartService.getProperty();
});
Service.js
angular.module('myapp')
.service('chartService', function(){
return {
getUrl: function init(path) {
Tabletop.init( { key: path,
callback: showInfo,
simpleSheet: true } )
}
}
function showInfo(data, tabletop) {
return{
getProperty: function(){
return data
},
setProperty: function(value){
data = value;
}
}
}
});
This is your service, the only thing i see you returning is the getUrl. so the only thing you will be able to access from the controller is chartService.getUrl function.
service('chartService', function ()
{
return
{
getUrl: function init(path)
{
Tabletop.init({
key: path,
callback: showInfo,
simpleSheet: true
})
}
}
function showInfo(data, tabletop)
{
return
{
getProperty: function ()
{
return data
},
setProperty: function (value)
{
data = value;
}
}
}
});
To Get it working, while I don't think this is the ideal solution it should work...
service('chartService', function ()
{
var returnObject =
{
getUrl: function init(path)
{
Tabletop.init({
key: path,
callback: showInfo,
simpleSheet: true
})
},
resultValue: {}
}
function showInfo(data, tabletop)
{
return
{
getProperty: function ()
{
return data
},
setProperty: function (value)
{
data = value;
returnObject.resultValue = value;
}
}
}
return returnObject
});
then replace chartService.getProperty() with chartService.resultValue although this is in no was synchronous.
I have a service which will make a call to the server and returns the data. I am binding service to a variable on scope.
Example:
Let the service be DataModelService
in the controller : $scope.data = DataModelService
in the view <div ng-repeat="value in data.persons">{{value.name}}</div>
My Code :
This is how my code looks like:
/**DataModelService**/
factory('DataModelService', [
'DataService',
function (DataService) {
var service;
service = {
changeState: function (params) {
DataService.changePersonState(params)
.then(function (response) {
service.loadData(response.data);
});
},
loadData: function (responseData) {
service.persons = responseData.persons;
}
}
return service;
}
]);
/**DataService**/
factory('DataService', ['$http',
function ($http) {
return {
changePersonState: function (params) {
return $http.post("url", params);
}
}
}
]);
/**DataController**/
.controller('DataController', ['DataModelService',
function (DataModelService) {
$scope.data = DataModelService;
}
]);
/view/
<div ng-repeat = "person in data.persons" >{{person.name}} </div>
On the view I am doing a ng-repeat on a key in data i.e. ng-repeat="value in data.persons"
and also I have an option to change the state of person to active or inactive, so whenver i make a change to the state of the person, a call is sent to the server and data is set into the Service and as it is binded to the view, it should automatically update the data. But whats happening in my case, ng-repeat is not removing old data and instead it is appending new data to the old data.
For me its not good approach to write promise callback (then) into service. Because in your case, DataModelService returns data with some delay but not promise. And we don't know when.
So the way to make it work to add basic $timeout and fetch data from service by using other method.
So my suggestion is Demo
and your fixed example: Demo2
If we will take your example, it should be like:
JS
var fessmodule = angular.module('myModule', ['ngResource']);
fessmodule.controller('fessCntrl', function ($scope, DataModelService, $timeout) {
$scope.alertSwap = function () {
DataModelService.changeState('ff');
$timeout(function(){
$scope.data = DataModelService.getResponse();
}, 10);
}
});
fessmodule.$inject = ['$scope', 'Data', '$timeout'];
/**DataModelService**/
fessmodule.factory('DataModelService', [ 'DataService',function (DataService) {
var value = [];
var service = {
changeState: function (params) {
DataService.changePersonState(params)
.then(function (response) {
value = response.persons;
});
},
getResponse : function(){
return value;
}
}
return service;
}
]);
/**DataService**/
fessmodule.factory('DataService', ['$q',function ($q) {
var data = { // dummy
persons: [{
name: "Bob"
}, {
name: "Mark"
}, {
name: "Kelly"
}]
};
var factory = {
changePersonState: function (selectedSubject) {
var deferred = $q.defer();
deferred.resolve(data);
return deferred.promise;
}
}
return factory;
} //function
]);