In the setup of my app, I use Restangular.setRequestInterceptor() to call a function that shows a loading screen anytime I make a request with Restangular.
However, there is one spot in my app where I don't want it to call that function. How can I tell Restangular to ignore the setRequestInterceptor function for this one call?
For anyone else that runs into this problem, it turns out Restangular lets you create a separate Restangular service with different configuration options than the global one. This example from the Restangular GitHub shows how:
// Global configuration
app.config(function(RestangularProvider) {
RestangularProvider.setBaseUrl('http://www.google.com');
RestangularProvider.setRequestSuffix('.json');
});
// Restangular service that uses Bing
app.factory('BingRestangular', function(Restangular) {
return Restangular.withConfig(function(RestangularConfigurer) {
RestangularConfigurer.setBaseUrl('http://www.bing.com');
});
});
// Let's use them from a controller
app.controller('MainCtrl', function(Restangular, BingRestangular) {
// GET to http://www.google.com/users.json
// Uses global configuration
Restangular.all('users').getList()
// GET to http://www.bing.com/users.json
// Uses Bing configuration which is based on Global one, therefore .json is added.
BingRestangular.all('users').getList()
});
Related
I have service something like this
angular.module('services').factory('DownloadService',[$resource,
function($resource){
return $resource('path/to/service/download', {}, {
downloadFile: {
method: 'GET',
url: 'path/to/service/download?fileID=:fileID'
}
});
}
]);
Then in controller i have function where i call this service and call that function on click on file
angular.module('search').controller('MainCtrl', ['$scope','DownloadService',
function ($scope,DownloadService){
$scope.downloadDocument = function(id){
DownloadService.downloadFile({
fileId: id
});
};
}])
I am getting this error
TypeError:DownloadService.downloadFile is not a function...
Ensure that you have services module specified as a dependency when you created the search module, i.e. something like
angular.module('search', ['services', ...])
Further, ensure that you do NOT have a different service within search or any of the other modules it depends on with the name DownloadService.
You might just want to add an alert or console.log in the services' DownloadService to make sure it is being instantiated.
Or better still, just rename it to something unique (say myDownloadService) in both places.
A console.log(new DownloadService()) and examining the object for $downloadFile is also another way to make sure that angular is injecting the right service.
You have a typo.
donwloadFile
and
DownloadService.downloadFIle
Currently I'm using ngResource for my RESTful API calls, and I'm using KARMA & jasmine to do my unit and integration tests.
Inside one Controller i have a function that expects promise to be finished:
var elem = new Element() // calling a ngResource Factory
elem.$save().then(function () {
$scope.elem.push(elem);
});
In my karma tests, i test if the list is empty, that call the function above and check if the $scope.elem Array does have the new created element. But since its a promise, KARMA test does not solve this. I tried to use $rootScope.apply(), but the $httpBackend expects that i define lots of calls, that are expected. But i just want to simulate the call.
Is there any elegant solution for that?
There is not elegant solution for this. Main purpose of testing is prepare "isolated" ecosystem for test. If you want to test ajax call , they must return something. You cant test and just tell "skip this promise and act as like it was success".
When you need to resolve any promise, i am using this.
$httpBackend.flush();
$rootScope.$apply();
This will call $httpBackend, and ofcourse it will expecting call. You have no choice
1.) Mock all backend calls (this is taken from my test)
identityBackend = $httpBackend.when("GET", AppConfig.API_IDENTITY_ENDPOINT + "/me",null,function(headers)
{
return headers.Authorization !== undefined;
}).respond(200, fakeAuthUser);
So it will respond with http 200 with fake json on request host/me , when authorization token inside headers is not undefined.
2.) Second choice, create mockable backend inside nodejs/express and mock all requests with jsons. Before starting jasmine test , you will also start this "fake" backend server.
I want to be able to modify the object I provide the stateHelperProvider.state(obj).
I have a module like this:
(function() {
'use strict';
angular
.module('myApp', [])
.config(stateConfig);
stateConfig.$inject = ['stateConfigObject', 'stateHelperProvider', 'someProvider'];
function stateConfig(stateConfigObject, stateHelperProvider, someProvider) {
someProvider.$get().getSomeData().then(function(response) {
// use the response here to modify the stateConfigObject
});
stateHelperProvider.state(stateConfigObject);
}
})();
Done that way, there will be an a-sync issue and the stateConfigObject will not be the correct one passed into the stateHelperProvider in the end. The config phase will probably finish before the a-sync stuff finishes. So, is there anyway to make this all happen synchronously?
I've tried using the stateHelperProvider inside someProvider.$get() like so, but still no luck:
someProvider.$get().getSomeData().then(function(response) {
// use the response here to modify the stateConfigObject
stateHelperProvider.state(stateConfigObject);
});
I struggled to title this question but basically I'm just starting off with angular and am using ngMaterial. I have a toast created by using an angular factory
app.factory('notify', ['$mdToast', '$animate', function($mdToast, $animate) {
return {
showToast: function(msg) {
var toast = $mdToast.simple()
.content(msg)
.action('Close')
.highlightAction(false)
.position('top right');
$mdToast.show(toast).then(function() {
//
});
}
}
}]);
This works great if I have a button on the page that activates the toast however I have socket.io running as well with node monitoring redis for updates to pop up that notification. However I can't get it to work as I'm not quite sure how I can call that factory from within here
socket.on('notification.new', function (data) {
//call factory here to show toast
console.log(data);
});
I know if I have it on a controller I can do it by using
angular.element().scope().showToast(data)
But I don't want to create an element just to house the controller to call the function.
What I did to solve this issue is I attached one of the functions inside the controller to the window object. So something like
window.showToast = function(msg) {
var toast = $mdToast.simple()
.content(msg)
.action('Close')
.highlightAction(false)
.position('top right');
$mdToast.show(toast).then(function() {
//
});
Then, from within the socket io listener (or any raw javascript for that matter):
socket.on('notification.new', function (data) {
//call factory here to show toast
window.showToast(data); //or however you'd like
});
And that kind of worked for me. I know this is not the best approach but since this question didn't have any answers at all I thought I'll post a workaround that at least does the job done.
You need to get hold of Angular services to use Angular in a raw Javascript.
Refer to Call Angular JS from legacy code
angular.element(domElement).scope() to get the current scope for the element
angular.element(domElement).injector() to get the current app injector
angular.element(domElement).controller() to get a hold of the ng-controller instance.
In your case use injector service to get hold of your factory.
Update 1
$injector reference
Could anybody suggest me a way how to mock $resource object
I've searched though internet, but all my tries were finished by KARMA testing.
I don't need it.
My idea is to have just fake object, so I will be able to switch between $resource implementations in my app.
Thanks.
You can use $provide to do this.
angular.module(“MyApp”,[])
.config([“$provide”,function($provide){
$provide.decorator(“$resource”,function($delegate, myReplacementResource){
//$delegate is the original $resource, if you just want to modify it
//either inject a replacement resource that you have already registered
//as a factory (recommended). Or make it here.
return myReplacementResource;
});
}])
dskh presented one way to do it. Here's a another way which you might find to be easier... although it's ofen used for unit testing, you can use angular-mocks.js in your app as well:
app.run(function($httpBackend) {
$httpBackend.whenPOST('/string/match/url').respond(function (method, url, data) {
return [{some:data}];
});
$httpBackend.whenGET(/regexpmatch/).respond(function (method, url, data) {
return {some:{other:data}};
});
// pass through other stuff
$httpBackend.whenPOST(/.*/).passThrough();
$httpBackend.whenGET(/.*/).passThrough();
$httpBackend.whenDELETE(/.*/).passThrough();
$httpBackend.whenJSONP(/.*/).passThrough();
$httpBackend.whenPUT(/.*/).passThrough();
});
This plunk shows how I go about mocking resource objects, from a angular service, in a controller. I use SinonJs to fake a resource object. Then I basically fake the promise chain by injecting $q.
To fake the promise chain you need to get a defer object from $q, then get a promise from it.
In your tests, you then either fake a success or a failure by calling promise.resolve() or promise.reject() on that promise. You can fake data from the server by passing an object in as a parameter like this promise.reject(someData).
You then have to make sure that you scope.apply(). To make sure that whatever it is you wanted to do becomes visible on scope.
I'm not entirely sure if this is the right way to go about this, but it has been working for me.