I have an ngResource object like this:
[...].factory('Event', ['$resource', function ($resource) {
return $resource('/events/:id', {id: '#id'}, {
resume: {url: '/events/:id/resume'},
signUpload: {url: '/events/:id/sign-upload'},
});
}]);
But when I call myModel.$resume(); or myModel.$signUpload() the returned data gets automatically saved to my model. However, the returned data is not my model attributes, but actually another completely different return.
I need to avoid auto-saving the returned data from the server. Is there anything out-of-the-box to do that? I couldn't find it here: https://docs.angularjs.org/api/ngResource/service/$resource
Thanks
For this case you can try to not use resource, but create service.
app.service('eventService', ['$http, $q', function ($http, $q) {
this.signUpload = function(eventId) {
var defer = $q.defer();
$http.get('/events/' + eventId + '/sign-upload')
.then(function(result) {
defer.resolve(result.data);
})
.catch(function(err) {
defer.reject(new Error(err));
});
return defer.promise;
}
// same for other function
}]);
Inject this service in controller, and just do eventService.signUpload(eventId);
Related
Hii I m using following code. I am reading a json file name is "users.json". If i read this file in controller through $http everything works fine. but i want to use the data that i read from file, again and again in different controller so i made a factory for this. but in factory when i read data from that json file through $http.get() and in return when i call that service method in my controller and it returns Object { $$state: Object }
app.factory('AboutFactory',['$http',function ($http) {
return {
getter: function () {
return $http({
method : 'GET',
url : '/home/penguin/Modeles/users.json',
cache : true
})
.then(function (response) {
return response.data
})
}
}
}])
Result of getter function is a promise. so you should use it like this:
AboutFactory.getter().then(function(res)
{
console.log(res);
});
That's because the $http service returns a promise as mentioned in the documentation:
The $http API is based on the deferred/promise APIs exposed by the $q
service. While for simple usage patterns this doesn't matter much, for
advanced usage it is important to familiarize yourself with these APIs
and the guarantees they provide.
You can think of a promise as if you give a top secret message to someone to deliver personally to a friend, then when delivered, report back to you with a message back from your friend.
You provide the message (the request object) to the person so that they can attempt to make the delivery of the message (send the request).
The attempted delivery has taken place (the request has been sent), it either:
a) was delivered successfully (successful response) or
b) your friend was not in so the letter could not be delivered (non success response).
You can then act depending on the response you get back
a) Message was delivered (it was a successful request) and you got a letter back (do something with the response) or
b) Message failed to get delivered (request wasn't successful), so you can maybe try again later or do something else as you don't have the information you requested
Here is an example of using the $http service with the $q service:
// app.js
(function() {
'use strict';
angular.module('app', []);
})();
// main.controller.js
(function() {
'use strict';
angular.module('app').controller('MainController', MainController);
MainController.$inject = ['AboutFactory'];
function MainController(AboutFactory) {
var vm = this;
AboutFactory.getter().then(function(data) {
// do something with your data
vm.data = data;
}, function(error) {
// give the user feedback on the error
});
}
})();
// about.service.js
(function() {
'use strict';
angular.module('app').factory('AboutFactory', AboutFactory);
AboutFactory.$inject = ['$http', '$q']
function AboutFactory($http, $q) {
var service = {
getter: getter
};
return service;
function getter() {
// perform some asynchronous operation, resolve or reject the promise when appropriate.
return $q(function(resolve, reject) {
$http({
method: 'GET',
url: 'https://httpbin.org/get',
cache: true
}).then(function(response) {
// successful status code
// resolve the data from the response
return resolve(response.data);
}, function(error) {
// error
// handle the error somehow
// reject with the error
return reject(error);
});
});
}
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<div ng-app="app" ng-controller="MainController as MainCtrl">
<pre>{{MainCtrl.data | json}}</pre>
</div>
Try this approach. It will work as per your expectation.
Read JSON file in controller through $http service as it is works fine.
For sharing the response data from one controller to another you can create a service and store the data into that service.
Service :
app.service('setGetData', function() {
var data = '';
getData: function() { return data; },
setData: function(requestData) { data = requestData; }
});
Controllers :
app.controller('myCtrl1', ['setGetData',function(setGetData) {
// To set the data from the one controller
var data = 'Hello World !!';
setGetData.setData(data);
}]);
app.controller('myCtrl2', ['setGetData',function(setGetData) {
// To get the data from the another controller
var res = setGetData.getData();
console.log(res); // Hello World !!
}]);
Here, we can see that myCtrl1 is used for setting the data and myCtrl2 is used for getting the data. So, we can share the data from one controller to another controller like this.
I need to pass a value from an input field on the view using a service. The service should call my WebAPI2 and then receives an valid JSON as a response.
However, I am either getting an promise object, which I cannot resolve (even with ".then()"), or if I'm using an factory it won't compile as it seems to not implement the $get method.
The JSON Object I'm returning is also valid.
View :
<div class="input" ng-controller="InputController as ctrl">
<input ng-model="inputdata" /> {{inputdata}}
<button ng-click="ctrl.gibDaten(inputdata)">Senden</button>
{{cooledaten}}
</div>
Controller :
module GoogleMapsApp {
myApp.myAppModule.controller("InputController",
["$scope", "mapsServiceCustom",
function ($scope, mapsServiceCustom) {
$scope.lEingabedaten = $scope.inputdata;
this.gibDaten = function () {
$scope.cooledaten = mapsServiceCustom.gibDaten().then();
console.log($scope.cooledaten);
}
}]);
}
Service:
module GoogleMapsApp {
myApp.myAppModule.service("mapsServiceCustom",
["$http",
function ($http) {
this.gibDaten = function (lEingabe) {
console.log(lEingabe);
console.log($http.get("api/getDistanceData/" + lEingabe + "/Cologne")
.then(function(data) {
return data;
Controller:}));
return $http.get("api/getDistanceData/" + lEingabe + "/Cologne")
.then(function (data) {
return data;
});
//return $http.get("api/getDistanceData/" + lEingabedaten1 + "/Cologne");
}
}
]);
}
Console log:
Object { $$state: Object }maps.serviceCustom.js:14:17
Object { $$state: Object }InputController.js:8:17
If I check the $$state:Object it contains exactly the desired data.
Using a factory leads me to the following error:
https://docs.angularjs.org/error/$injector/undef?p0=mapsServiceCustom
So what am I doing wrong? How would I implement my intend?
You need to pass a function to then part...
So just put then function in your controller and set returning response to your variable...
myApp.myAppModule.controller("InputController",
["$scope", "mapsServiceCustom",
function ($scope, mapsServiceCustom) {
$scope.lEingabedaten = $scope.inputdata;
this.gibDaten = function () {
mapsServiceCustom.gibDaten().then(function(response){
// set response to your variable
$scope.cooledaten = response;
});
}
}]);
You have not implemented the service properly. please go through the following link (Angularjs official documentation)
https://docs.angularjs.org/guide/services
You need to expose your API by returning it an js object.(Same thing is shown in your error link. please refer to that as well)
module GoogleMapsApp {
myApp.myAppModule.service("mapsServiceCustom",
["$http", function ($http) {
this.gibDaten = function (lEingabe) {
console.log(lEingabe);
console.log($http.get("api/getDistanceData/" + lEingabe + "/Cologne")
.then(function(data) {
return data;
}
}
return { gibDaten: this.gibDaten};
}]);
}
Here You can learn more on $get
method https://docs.angularjs.org/guide/providers
I'm fairly new to AngularJS and have just begun to grasp many of the concepts I especially like the MVC design pattern. But I am having a difficult time implementing the Service layer in my application.
What I am finding is that after my Controller calls a method within the service, it continues with code execution before the service returns the data; so that by the time the service does return the data, it isn't of any use to the controller.
To give a better example of what I'm saying, here is the code:
var InsightApp = angular.module('InsightApp', ['chart.js']);
// Module declaration with factory containing the service
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function () {
return $http.get('Home/GetSalesData')
.then(function (result) {
return result.data;
});
}
};
});
InsightApp.controller("ChartSelectionController", GetAvailableCharts);
// 2nd Controller calls the Service
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections();
// This method is executed before the service returns the data
function workWithData(response){
// Do Something with Data
}
}
All the examples I've found seem to be constructed as I have here or some slight variation; so I am not certain what I should be doing to ensure asynchronous execution.
In the Javascript world, I'd move the service to the inside of the Controller to make certain it executes async; but I don't how to make that happen in Angular. Also, it would be counter intuitive against the angular injection to do that anyway.
So what is the proper way to do this?
http return a promise not the data, so in your factory your returning the $http promise and can use it like a promise with then, catch, finally method.
see: http://blog.ninja-squad.com/2015/05/28/angularjs-promises/
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections()
.then(function(res) {
// execute when you have the data
})
.catch(function(err) {
// execute if you have an error in your http call
});
EDIT pass params to model service:
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function (yourParameter) {
console.log(yourParameter);
return $http.get('Home/GetSalesData')
.then(function (result) {
return result.data;
});
}
};
});
and then :
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections('only pie one')
.then(function(res) {
// execute when you have the data
})
.catch(function(err) {
// execute if you have an error in your http call
});
You should proceed like this :
DataService.GetChartSelections().then(function (data) {
workWithData(data);
}
Actually $http.get returns a Promise. You can call the method then to handle the success or failure of your Promise
Should it not be like this, when your $http returns a promise or you pass a callback.
With passing callback as a param.
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function (workWithData) {
return $http.get('Home/GetSalesData')
.then(function (result) {
workWithData(result.data);
});
}
};
});
Controller code:
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections(workWithData);
// This method is executed before the service returns the data
function workWithData(response){
// Do Something with Data
}
}
Or use then or success:
var response = DataService.GetChartSelections().then(function(res){
//you have your response here... which you can pass to workWithData
});
Return the promise to the controller, dont resolve it in the factory
var InsightApp = angular.module('InsightApp', ['chart.js']);
// Module declaration with factory containing the service
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function () {
return $http.get('Home/GetSalesData');
}
};
});
In the controller,
var successCallBk =function (response){
// Do Something with Data
};
var errorCallBK =function (response){
// Error Module
};
var response = DataService.GetChartSelections().then(successCallBk,errorCallBK);
I'm trying to learn how to use Angular right, by having all my business logic in services.
When I do a post request in a service, I get the following error:
Cannot read property 'post' of undefined
Here is some code:
UrlApp.controller('UrlFormCtrl', UrlFormCtrl);
UrlApp.factory('addUrlService', addUrlService);
function UrlFormCtrl($scope, $http) {
console.log('Url Form Controller Initialized');
$scope.addUrl = addUrlService.bind(null, $http);
}
function addUrlService($scope, $http){
console.log('initializing addUrlService');
return $http.post('urls/create', {'test':'test'}).then(function(response){
return response.data;
});
}
I'm just getting the hang of Angular, so I'm not entirely sure what I'm doing wrong. See any problems?
Firstly, you don't need to inject $scope in your service.
Secondly, you don't need to inject $http service in your controller.
Thirdly, you need to inject the service in your controller.
Finally, addUrlService service is returning a promise meaning it will make a request when service is instantiated. You may want to return a function instead or an object containing several functions.
So I would change your code to:
UrlApp.controller('UrlFormCtrl', UrlFormCtrl);
UrlApp.factory('AddUrlService', AddUrlService);
function UrlFormCtrl($scope, AddUrlService) {
$scope.addUrl = AddUrlService.addUrl;
}
function AddUrlService($http) {
function addUrl() {
return $http.post('urls/create', {
'test': 'test'
}).then(function (response) {
return response.data;
});
}
return {
addUrl: addUrl
};
}
Can you try like this
UrlApp.controller('UrlFormCtrl', UrlFormCtrl);
UrlApp.factory('addUrlService', addUrlService);
function UrlFormCtrl($scope,addUrlService) {
console.log('Url Form Controller Initialized');
$scope.addUrl = addUrlService;
}
function addUrlService($http){
console.log('initializing addUrlService');
return $http.post('urls/create', {'test':'test'}).then(function(response){
return response.data;
});
}
I'm getting crazy with this since a couple of hours.
I have an angular service factory to get addresses from my API:
App.factory('storesService', ['$http', '$q', 'endpoint', function ($http, $q, endpoint) {
var deferred = $q.defer();
return {
addresses: function (store_id) {
$http.get(endpoint.store.addresses, {
params: {
id: store_id
}
})
.success(function (data) {
console.log('Data from API:' + data);
deferred.resolve(data);
})
.error(function () {
deferred.reject();
});
return deferred.promise;
}
};
}]);
This service is used in my controller to get addresses of a specific store:
$scope.loadAddresses = function (store_id) {
var load = storesService.addresses(store_id);
load.then(function (data) {
console.log('Deferred data:' + data);
$scope.addresses = data.addresses;
});
};
In my view I have the ng-init="loadAddresses(store_id)", store_id is a right value.
I'm also using angular-xeditable (select-local) to manage my store selection.
I added onaftersave='storeChanged(store.id)' in my view to get the store id selected by the user and it return correctly the new id.
my storeChanged function is very easy, it basically run a new request to the API:
$scope.storeChanged = function (store_id) {
$scope.loadAddresses(store_id);
};
What happen:
At the beginning, with ng-init I see correctly the console.log, first the one from the service and then the one from the controller.
Once I select another store from my select I first see the console.log from the controller and then the one from the service.
Basically the data in the controller is not updated and I can not understand why it happen...
You defined your deferred globally in the service, so there is only one global promise. Because a promise can only be resolved or rejected once, it will stay resolved/rejected forever after your first http call. To fix simply move the line var deferred = $q.defer(); into your service function:
App.factory('storesService', ['$http', '$q', 'endpoint', function ($http, $q, endpoint) {
return {
addresses: function (store_id) {
var deferred = $q.defer();
$http.get(endpoint.store.addresses, {
params: {
id: store_id
}
})
.success(function (data) {
console.log('Data from API:' + data);
deferred.resolve(data);
})
.error(function () {
deferred.reject();
});
return deferred.promise;
}
};
}]);
You've created one defer for potentially many requests. The first time you make a request it will work, but after than it will instantly return, as the one promise you've set up has already resolved. Patterns smilar to this can be very useful for caching, actually.
$http already returns a promise. You don't need to go out of your way to use $q
App.factory('storesService', ['$http', 'endpoint', function ($http, endpoint) {
return {
addresses: function (store_id) {
return $http.get(endpoint.store.addresses, {
params: {
id: store_id
}
}).then(function(response){
//Chain an extra promise here to clean up the response to just return the data.
return response.data;
})
}
};
}]);
You're trying to re-resolve a promise, which you can't do. You only create one deferred that every request uses. That should be inside of the addresses function so that a new one is created for each request, but you don't need it anyway because $http creates and returns a promise already. You need to return the promise from $http rather than creating a new one. See this post for a better understanding: What is the explicit promise construction antipattern and how do I avoid it?
addresses: function (store_id) {
return $http.get(endpoint.store.addresses, {
params: {
id: store_id
}
}).then(function(resp) {
console.log('Data from API:' + resp.data);
return resp.data;
});
}