AngularJS - update data using services factory with $resource from another controller - angularjs

I meet a problem with $resource of angularjs
I have a service factory :
angular.module('publicApp').factory('Model', function ($resource) {
var totalStock = $resource('./resource/data/totalStock',{},{}});
return {
totalStock : totalStock
}
});
And a controller get data from service :
angular.module('publicApp')
.controller('ManageCtrl', function ($scope, Model) {
$scope.total = Model.totalStock.query();
});
then, in another controller, when a function inside it success, I recall the services :
angular.module('publicApp')
.controller('ActionCtrl', function ($scope, Model) {
$scope.checkout = function () {
$http.post('/resource/action/sold', formData).success(function (resp) {
if (resp.resCode == -1) {
alert(resp.result);
return;
}
console.log('sold!');
Model.totalStock.query();
});
}
});
My idea that when Model.totalStock.query() service recall, the $scope.total value of ManageCtrl is updated also. Anyone suggest me do it in right way?

I am not sure, but this may work:
You can create two factories:
'ModelRessource' factory is only used by your 'Model' factory.
angular.module('publicApp').factory('ModelRessource', function ($resource) {
var totalStock = $resource('./resource/data/totalStock',{},{}});
return {
totalStock : totalStock
}
});
Then, you use 'Model' factory to interact with your ressource. If you bind your $scope to Model.totalStack, every time refreshTotalStack() is call, totalStack should be updated.
angular.module('publicApp').factory('Model', function (ModelRessource) {
var data = {};
data.totalStack = {};
return {
totalStack : data.totalStack,
refreshTotalStack : function () {
ModelRessource.totalStock.query(function (resp) {
data.totalStack = resp;
return data.totalStack;
});
}
}
});

Related

Angular Service doesn't return value

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.

Send path from controller to a service which will return a promise back to controller

I have a service which get data from a file(path is given by the controller) and return a promise - then another service that create a object with properties using the returned data from the last service.
My problems are:
The getDataService runs before controller so it has no path from which to fetch data => nothing in return(an error)
Provider 'GetDataService' must return a value from $get factory method.
I need to keep this structure because I'll have more controllers with different paths to give
I'm also opened to other solutions but I need to make sure that datas are loaded before the template get populated. I've tried to call SetProperties service first with getData service into it - but still getData.js is executed first
getdata Service
angular.module('myApp').factory('GetDataService',['$http', function($http) {
var getData = function(path){
return $http.get(path).then(function(result) {
return result.data;
});
};
}]);
setProperties service
angular.module('myApp').service('PageProperties',['$http', function($http) {
this.setProps = function(page, data) {
some code here
var properties = {
isCenterActive : isActive_val,
//header elements
titleClass : page,
title : data.titles[page],
//footer elements
leftLink : leftLink_val,
leftFooterClass: leftLink_val,
leftTitle: data.titles[leftLink_val],
centerLink : centerLink_val,
centerFooterClass: data.titles[centerLink_val],
centerTitle : centerTitle_val,
rightLink : rightLink_val,
rightFooterClass: rightLink_val ,
rightTitle : data.titles[rightLink_val],
}
return properties;
}
}]);
controller
angular.module('myApp', [])
.controller('meniuController', ['$http', '$stateParams', '$scope', 'GetDataService', 'PageProperties',
function($http, $stateParams, $scope, GetDataService, PageProperties){
var page = "meniu";
$scope.language = $stateParams.lang;
var path = '_global/views/services/json/' + $stateParams.lang + '_data.json';
/*PageProperties.setProps(page, path).then(function(data){
//some code here
});*/
GetDataService.getData(path).then(function(data){
$scope.props = PageProperties.setProps(page, data);
}).catch(function(){
$scope.error = 'Unable to get data';
});
}])
Thanks in advance!!
The error says your GetDataService provider (defined as factory) doesn't return anything
angular.module('myApp').factory('GetDataService',['$http', function($http) {
var getData = function(path){
return $http.get(path).then(function(result) {
return result.data;
});
};
// you need to actually return something
return { getData: getData };
}]);
Then you can make your PageProperties use GetDataService
angular
.module('myApp')
.service('PageProperties',['GetDataService', function(GetDataService) {
this.getProperties = function(path) {
return GetDataService.getData(path).then(/*transform here*/)
}

Inject different data to same controller

I have a controller that will have identical functionality to another by manage different data. I am new to angularJS so I'm not exactly sure how to proceed. I've read about services and factories but have only seen examples of injecting the same data across different controllers instead of different data to the same controller. Any help to point me in the right direction is appreciated.
angular.module("myApp")
.controller("AirlineController", function () {
this.Airlines = getAirlines(); //some service call that will be ajax eventually
});
angular.module("myApp")
.controller("CitiesController", function () {
this.Cities = getCities();//some service call that will be ajax eventually
});
angular.module("myApp")
.controller("GenericController", function () {
$('.selected-items-box').bind('click', function (e) {
e.stopPropagation();
$('.image-select-wrapper .list').toggle('slideDown');
});
$(document).bind('click', function () {
$('.image-select-wrapper .list').slideUp();
});
this.ListObject = getAirlines();//this list should be populated from one of the other controllers
this.toggleSelected = function (selectedItem) {
angular.forEach(this.ListObject, function (ListItem) {
ListItem == selectedItem ? ListItem.selected = true : ListItem.selected = false;
});
};
this.getSelectedItem = function (item) {
return item.selected;
};
});
Use function parameters to making a factory more versatile.
app.factory("getGeneric", function($http) {
var apiUrl = "http:/my.com/api/"
//Use function parameter
return function (arg1) {
//return promise
return $http.get(apiUrl + arg1);
}
});
Then in your controllers.
app.controller("AirlineController", function (getGeneric) {
var vm = this;
//use function parameter
var airlinesPromise = getGeneric("Airlines"); //service returns promise
airlinesPromise.then( function onFulfilled(response) {
vm.Airlines = response.data;
});
});
app.controller("CitiesController", function (getGeneric) {
var vm = this;
//use function parameter
var citiesPromise = getGeneric("Cities"); //service returns promise
citiesPromise.then( function onFulfilled(response) {
vm.Cities = response.data;
});
});
Please notice that most servive APIs are asynchronous and do not return data immediately. The AngularJS $http service returns promises and data needs to be extracted from the promise with its .then method.
Another point is make factories generic and make controllers lean and specific. Controllers should be lean and specific to their HTML.
You can certainly achieve that. You can have a factory/service that has the methods with parameters that you can pass from the controller. For example I have two controllers and one service that both the controllers are calling.
Based on the the parameter values passed, the service will return different set of data. I'm using the $scope but you can use this but the idea remains the same.
angular.module('SelectOptionModule')
.controller('AirlineController', function ($scope, AirlineService) {
$scope.Airline = AirlineService.GetAirLines("a")
});
angular.module('SelectOptionModule')
.controller('Airline2Controller', function ($scope, AirlineService) {
$scope.Airline = AirlineService.GetAirLines("b")
});
angular.module('SelectOptionModule')
.factory('AirlineService', AirlineService);
function AirlineService() {
function GetAirLines(value) {
if (value == "a")
{
return [{ "Id" : "1", "Name" : "AA" } ]
}
if (value == "b") {
return [{ "Id": "2", "Name": "Delta" }]
}
}
return {
GetAirLines: GetAirLines
};
}
The View can be like to test this out.
<div ng-app='SelectOptionModule' >
<div ng-controller="AirlineController">
{{ Airline }}
</div>
<div ng-controller="Airline2Controller">
{{ Airline }}
</div>
</div>

pass data between controllers in AngularJS dynamically [duplicate]

This question already has answers here:
Share data between AngularJS controllers
(11 answers)
Closed 2 years ago.
i have tow controller in angularjs. if one controller change data other controller display updated data. in fact first controller has a event that it occur second controller display it. for this propose i wrote a service. this service has tow function. here is my service code.
app.service('sharedData', function ($http) {
var data=[]
return {
setData: function () {
$http.get('/getData').success(function(response){
data = response;
})
},
getData: function(){
return data;
}
}
});
in first controller
app.controller("FirstController", function ($scope, $http,sharedData)
{
$scope.handleGesture = function ($event)
{
sharedData.setData();
};
});
in second controller:
app.controller("SecondController", function ($scope,sharedData) {
var data=[];
data = sharedData.getData();
}
);
in first controller setData work with out any problem but in second controller not work correctly. how to share data dynamically between tow controllers?
You are on the right track with trying to share data between controllers but you are missing some key points. The problem is that SecondController gets loaded when the app runs so it calls sharedData.getData() even though the call to setData in the firstController does not happen yet. Therefore, you will always get an empty array when you call sharedData.getData().To solve this, you must use promises which tells you when the service has data available to you. Modify your service like below:
app.service('sharedData', function ($http, $q) {
var data=[];
var deferred = $q.defer();
return {
setData: function () {
$http.get('/getData').success(function(response){
data = response;
deferred.resolve(response);
})
},
init: function(){
return deferred.promise;
},
data: data
}
})
And the secondController like this:
app.controller("SecondController", function ($scope,sharedData) {
var data=[];
sharedData.init().then(function() {
data = sharedData.data;
});
});
For more info on promises, https://docs.angularjs.org/api/ng/service/$q
You had multiple syntax problems, like service name is SharedData and you using it as SharedDataRange, the service is getting returned before the get function.
What I have done is corrected all the syntax errors and compiled into a plunkr for you to have a look. Just look at the console and I am getting the data array which was set earlier in the setter.
Javascript:
var app = angular.module('plunker', []);
app.controller("FirstController", function ($scope,sharedDateRange)
{
sharedDateRange.setData();
});
app.controller("SecondController", function ($scope,sharedDateRange) {
var data=[];
data = sharedDateRange.getData();
console.log(data);
});
app.service('sharedDateRange', function ($http) {
var data=[];
return {
setData: function () {
data = ['1','2','3'];
}
,
getData: function(){
return data;
}
}
});
Working Example
If you want to keep sharedDataRange as the variable name and service name as sharedData have a look at this example
javascript:
var app = angular.module('plunker', []);
app.controller("FirstController", ['$scope','sharedData', function ($scope,sharedDateRange)
{
sharedDateRange.setData();
}]);
app.controller("SecondController", ['$scope','sharedData', function ($scope,sharedDateRange) {
var data=[];
data = sharedDateRange.getData();
console.log(data);
}]);
app.service('sharedData', function ($http) {
var data=[];
return {
setData: function () {
data = ['1','2','3'];
}
,
getData: function(){
return data;
}
}
});
You can bind the data object on the service to your second controller.
app.service('sharedData', function ($http) {
var ret = {
data: [],
setData: function () {
$http.get('/getData').success(function(response){
data = response;
});
}
};
return ret;
});
app.controller("FirstController", function ($scope, sharedData) {
$scope.handleGesture = function () {
sharedData.setData();
};
});
app.controller("SecondController", function ($scope, sharedData) {
$scope.data = sharedData.data;
});
What you need is a singleton. The service sharedData needs to be a single instance preferably a static object having a static data member. That way you can share the data between different controllers. Here is the modified version
var app = angular.module('app', []);
app.factory('sharedData', function ($http) {
var sharedData = function()
{
this.data = [];
}
sharedData.setData = function()
{
//$http.get('/getData').success(function(response){
this.data = "dummy";
//})
}
sharedData.getData = function()
{
return this.data;
}
return sharedData;
})
.controller("FirstController", function ($scope, $http,sharedData)
{
sharedData.setData();
})
.controller("SecondController", function ($scope,sharedData) {
$scope.data=sharedData.getData();
});
I have removed the event for testing and removed the $http get for now. You can check out this link for a working demo:
http://jsfiddle.net/p8zzuju9/

Angular service wire up not working

I have written a service, depending on an other service. But initialisation is not working.
You can find a plunker as showcase
Should be close to working... Any tipps?
Thanks in advance!
edit: The plunker is fixed now and can be used as reference.
You need to either change your testServiceMockConfig and testService from factory to service, for example:
.service('testServiceMockConfig', function ()
or keep them as factories and add return.this; at the bottom of both of them or restructure them like this (recommended):
angular.module('testServiceMockConfig', [])
.factory('testServiceMockConfig', function() {
console.log("setup cqrs mock config.");
return {
doLoadItems: function(callback) {
console.log("mock loading data");
if (!this.configuredLoadItems) {
throw Error("The mock is not configured to loadItems().");
}
callback(this.loadItemsError, this.loadItemsSuccess);
},
whenLoadItems: function(success, error) {
this.configuredLoadItems = true;
this.loadItemsSuccess = success;
this.loadItemsError = error;
}
};
});
I also assume that loadItems in testService should call:
testServiceMockConfig.doLoadItems(callback);
instead of:
testService.doLoadItems(callback);
As I see from your example,
you didn't define properly the factory. The this key used for service
in testService.doLoadItems(callback); replace with testServiceMockConfig.doLoadItems(callback);
The difference between service - factory - provider and definition you can find in this simple demo:
Fiddle
Fixed example:
angular.module('testServiceMockConfig', [])
.factory('testServiceMockConfig', function () {
console.log("setup cqrs mock config.");
return{
doLoadItems : function (callback) {
console.log("mock loading data");
if (!this.configuredLoadItems) {
throw Error("The mock is not configured to loadItems().");
}
callback(this.loadItemsError, this.loadItemsSuccess);
},
whenLoadItems : function (success, error) {
this.configuredLoadItems = true;
this.loadItemsSuccess = success;
this.loadItemsError = error;
}
}
});
angular.module('testService', ['testServiceMockConfig'])
.factory('testService', ['testServiceMockConfig', function (testServiceMockConfig) {
console.log("mock version. testServiceMockConfig: ");
return {
loadItems : function (callback) {
testServiceMockConfig.doLoadItems(callback);
}
}
}])
angular.module('ItemApp', ['testService'])
.controller('ItemsCtrl', ['$scope', 'testService', function ($scope, testService) {
$scope.text = 'No items loaded';
testService.loadItems(function (error, items) {
if (error) {
$scope.text = "Error happened";
}
$scope.text = '';
for (i = 0; i < items.length; i++) {
$scope.text = $scope.text + items[i].name;
}
})
}]);
Demo Plunker

Resources