Using service, ngResource save - javascript

I'm new to Angular.
I have this Service(?) for my RESTful services.
.factory('LanguagesService', function ($resource) {
return $resource('http://127.0.0.1:8000/language/:langId', {
langId: '#id'
});
});
Then in my controller I do like this
adminLang.addLanguage = function () {
LanguagesService.save({
code: adminLang.newCode,
name: adminLang.newName
});
}
My question is, how do I know if the save() is successful? So I can do this or that depending on if it fails or succeeds?
Thank you a lot.

When you request add two callback functions as below:
LanguagesService.save({
code: adminLang.newCode,
name: adminLang.newName
}, function(response){
// success
}, function(error){
// error
});
Check this for more information: http://fdietz.github.io/recipes-with-angular-js/consuming-external-services/consuming-restful-apis.html

$resource methods returns a promise object via $promise object, you could keep eye on that promise by placing .then.
Code
LanguagesService.save({
code: adminLang.newCode,
name: adminLang.newName
}).$promise.then(function(data){
console.log(data);
//do other awesome things
}, function(err){
});

Related

Angular JS : Not able to test service function with promises in Jasmine

Here, _fact is a reference to the service.
it('Git Check', function() {
$scope.user = 'swayams'
var data;
_fact.Git($scope).then(function(d) {
expect(d.data.length).toEqual(4)
}, function() { expect(d).not.toBeNull(); });
});
I am getting the error
SPEC HAS NO EXPECTATIONS Git Check
Update
After forcing async as per #FelisCatus and adding $formDigest, I am getting a different error Error: Unexpected request: GET https://api.github.com/users/swayams/repos
No more request expected
The updated code snippet looks something like -
it('Git Check', function(done) {
$scope.user = 'swayams'
var data;
_fact.Git($scope).then(function(d) {
expect(d.data.length).toEqual(4)
}, function() { expect(d).not.toBeNull(); });
});
$rootScope.$formDigest();
I have a Plunk here illustrating the issue.
Jasmine is not seeing your expectations because your function returns before any expect() is called. Depending on your situation, you may want to use async tests, or use some promise matchers.
With async tests, you add an additional argument to your test function, done.
it('Git Check', function (done) {
$scope.user = 'swayams'
var data;
_fact.Git($scope).then(function(d) {
expect(d.data.length).toEqual(4);
}, function() { expect(d).not.toBeNull(); }).finally(done);
$rootScope.$digest();
});
(Note the finally clause in the end of the promise chain.)
Please note that you have to do $rootScope.$digest() for the promises to resolve, even if your code is not using it. See: How to resolve promises in AngularJS, Jasmine 2.0 when there is no $scope to force a digest?

Mobile first - Encrypted Cache Success and Failure Handler

In MobileFirst V6.3 once we call a JSON Store API, Success and failure can be captured using .then() & .fail(). To chain the API calls we can use multiple .then(). Let's say,
WL.JSONStore.startTransaction()
.then(function () {
var data = [{name: 'carlos'}];
return WL.JSONStore.get(collectionName).add(data);
})
.then(function () {
var docs = [{_id: 1, json: {name: 'carlos'}}];
return WL.JSONStore.get(collectionName).remove(docs);
})
.then(function () {
return WL.JSONStore.commitTransaction();
})
.fail(function (errorObject) {
WL.JSONStore.rollbackTransaction()
.then(function () {
// Handle rollback success.
})
.fail(function () {
// Handle rollback failure.
})
});
Since Encrypted Cache API has its own API's callback methods, like below.
WL.EncryptedCache.open(credentials, create_if_none, onCompleteHandler, onErrorHandler);
How to handle Encrypted Cache API chain call's similar to JSON Store[Avoiding callback methods for each API Call's]?
If its not available in out-of-box, is any work around available to achieve the same.
A snippet will be helpful.
The recommendation is to use JSONStore.
Chaining callbacks is not supported out of the box.
The way to do it, is for someone to implement wrappers for the methods that are using callbacks. If you insist on doing that, you'll need to implement something that will look like this:
function wrapper() {
var myVar = $.Deferred();
Wl.EncryptedCache.open(credentials, create_if_none, myVar.resolve, myVar.reject);
return myVar;
}
From the user's code:
wrapper.then(
function() {success flow...},
function() {failure flow...}
);

Backbone JS save functionality

I have written a rails back end to my project and when you save or create a new record,among the status 200 and a json representation of the post that was saved.
When I do the following in bacbone:
modelObject = new App.Models.Post();
modelObject.set({title: 'asdasdas', content: 'asdadasdasdasdasd'});
if (modelObject.isValid()){
modelObject.save().then( ... )
}
How do I get the post object that is returned? (assuming the post is successful).
On the rails side, when I do #post.save I also do render json: #post, status: 200 on a successful save in the create action so there is a json object coming back, I just dot know how to access it on the backbone side.
The backbone docs describe few ways how can you get response from server after calling save() function.
For example:
You need to specify error and success callbacks:
var model = new App.Models.Post();
model.set({title: 'some title', content: 'some content'});
var options = {
success: function(model, response){
console.log('success handler');
model.set({id: response.id});
},
error: function(model, xhr){
console.log('error handler');
}
};
Specify wait option to wait response from server before set model attributes:
options.wait = true;
Need to call save function with specified options:
if (model.isValid()) {
model.save({}, options);
}
The modelObject.save() call will return a promise object. You should chain a .done() call to that and pass it in a function, like this:
modelObject.save().done(function(e) {
// handle your response here
});
You could also handle a failure the same way using the .fail() function. Chain them together like this:
modelObject.save().done(function(e) {
// handle your response here
}).fail(function(e) {
// handle failure here
});
Here's another way to write the same code:
var promise = modelObject.save();
promise.done(function(e) {
// handle your response here
});
promise.fail(function(e) {
// handle failure here
});
There is also a .always() that you could chain to always be called:
var promise = modelObject.save();
promise.done(function(e) {
// handle your response here
});
promise.fail(function(e) {
// handle failure here
});
promise.always(function(e) {
// always call this on success or failure
});

angular.js ui + bootstrap typeahead + asynchronous call

I'm using typeahead with the angular.js directive but my function to populate the autocomplete makes an asynchronous call and I can't return it to populate the autocomplete. Is there anyway to make it work with this asynchronous call?
Can I assume that you are using the typeahead of Bootstrap 2.x ?
If so, in the documentation, the description of the source field of typeahead()'s options is this:
The data source to query against. May be an array of strings or a
function. The function is passed two arguments, the query value in the
input field and the process callback. The function may be used
synchronously by returning the data source directly or asynchronously
via the process callback's single argument.
You can definitely pass in an async function as the source attr. The source function could be something like:
function someFunction(query, process) {
someAsyncCall(...query or so... , function(res) { // success callback
process(res);
}, function(err) { // error callback
process(null);
});
}
Update:
If you are using Angular Bootstrap's typeahead, it should be even easier. According to Angular Bootstrap's docs(http://angular-ui.github.io/bootstrap/), you can just return a promise for the typeahead function. Some example from the docs:
$scope.getLocation = function(val) {
return $http.get('http://maps.googleapis.com/maps/api/geocode/json', {
params: {
address: val,
sensor: false
}
}).then(function(res){
var addresses = [];
angular.forEach(res.data.results, function(item){
addresses.push(item.formatted_address);
});
return addresses;
});
};
A simpler one could be:
$scope.getSomething= function(query) {
var promise = $http.get('...some url...', {
params: {
queryName: query
}
});
return promise;
};
Or you can build your own promise:
$scope.getSomething= function(query) {
var deferred = $q.defer();
someAsyncCall(...query or so... , function(res) { // success callback
deferred.resolve(res);
}, function(err) { // error callback
deferred.reject(err);
});
return deferred.promise;
};
Actually, many services like $http are just returning promises when you call them.
More about promise in AngularJS: https://docs.angularjs.org/api/ng/service/$q

AngularJS $resource parameter is not replaced with its real value?

I have recently decided to use $resource for REST service, but I quickly got in trouble. I have a simple URL:
/r/interface/activate/:active/addr/:address
But calling it in unit test make it fail with:
// expected: POST /r/interface/activate/false/addr/123
// got : POST /r/interface/activate/false/addr/#address
My defined resource is :
module.factory('NetworkInterfaceActivationService', function ($resource) {
return $resource("/r/interface/activate/:active/addr/:address", {}, {
activate:{method:'POST', params:{active:"true", address:'#address'}, isArray:false},
deactivate:{method:'POST', params:{active:"false", address:'#address'}, isArray:false}
});
});
And this is how I call my service !
$scope.deactivateNetworkAddress = function (address) {
NetworkInterfaceActivationService.deactivate({address:address});
};
Am I missing something?
I tried your code with Angular 1.3, but I couldn't reproduce the problem.
jsFiddle
<button ng-click="parentCtrl.doIt('123foobar')">execute</button>
app.controller('ParentCtrl', function (NetworkInterfaceActivationService) {
this.doIt = function (address) {
NetworkInterfaceActivationService.deactivate({address:address});
};
})
app.factory('NetworkInterfaceActivationService', function ($resource) {
return $resource("/r/interface/activate/:active/addr/:address", {}, {
activate:{method:'POST', params:{active:"true", address:'#address'}, isArray:false}
});
});
HTTP call in console:
POST .../r/interface/activate/false/addr/123foobar

Categories

Resources