How to use $resource in Angular service - angularjs

Hello I need to find/update users from a mongodb collections via angular.
And I need to find them by _id and by username, so I created a service like this:
// Users service used for communicating with the users REST endpoint
angular.module('users').factory('Users', ['$resource',
function($resource) {
return $resource('users/:id', {}, {
update: {
method: 'PUT'
}
});
}
]);
And on Express I have the relative API route:
app.route('/users/:userId').put(users.update);
Now, suppose I have another express route like this to check username availability:
app.route('/users/:username').get(users.check);
How can I integrate this last one in the same angular service?
UPDATE:
Solved with this, is it right?
angular.module('users').factory('Users', ['$resource',
function($resource) {
return {
byId: $resource('users/:id', {}, {
update: {
method: 'PUT'
}
}),
byUsername: $resource('users/:username', {}, {
})
};
}
]);

Do you want to do something like this?
Angular service:
angular.module('users').factory('Users', function($resource) {
var resource = $resource('users/:byAttr/:id', {}, {
update: {
method: 'PUT',
isArray: false,
cache: false
}
});
return {
updateById: function (id) {
resource.update({id: id, byAttr: 'id'});
},
updateByName: function (username) {
resource.update({username: username, byAttr: 'username'});
},
}
});
Routes:
app.route('/users/id/:userId').put(users.update);
app.route('/users/user/:username').get(users.check);

Related

Global ngResource base

I have multiple factories in my angular service located in different js file. And there is common base of all the queries:
1) Authorization: Bearer token (header) (required after login)
2) AccessDateTime, UserIPAddress (required before login)
3) AccessDateTime, UserIPAddress, UserID (required after login)
Now, I find that it is very tedious to repeat this on each of the resource. How could i make a base for this? I thought that this is something very common but i could not found any documentation on this. Something like jquery.AjaxSetup().
Default Code
angular.module('app.test').factory('Test', ['$resource',
function($resource) {
return {
resource1: $resource(
url: 'test1/:testId/:AccessDateTime/:UserIPAddress',
headers: { Authorization: Bearer token},
params: { testId: '#_id', AccessDateTime:'#AccessDateTime', UserIPAddress: '#UserIPAddress' }
}),
resource2: return $resource(
url: 'test2/:testId/:AccessDateTime',
params: { testId: '#_id', AccessDateTime:'#AccessDateTime' }
});
}
}
]);
Code after base resource implemented(Illustration only)
angular.module('app.base').factory('FactoryBase'), ['resource',
function($resource) {}
if (resource need authorization) {
auto append header, AccessDateTime, UserIPAddress
} else if (resource do not need authorization) {
auto append AccessDateTime
}
// depending on attribute set with authorize: true/false
}
]);
angular.module('app.test').factory('Test', ['$resource',
function($resource) {
require('FactoryBase'),
return {
resource1: $resource(
url: 'test1/:testId',
authorize: true
}),
resource2: $resource(
url: 'test2/:testId',
authorize: false
}),
}
]);
Put modifier functions in your factory:
angular.module('app.test').factory('Test', ['$resource',
function($resource) {
var defaultConfig1 = {
url: 'test1/:testId/:AccessDateTime/:UserIPAddress',
headers: { Authorization: Bearer token},
params: { testId: '#_id',
AccessDateTime:'#AccessDateTime',
UserIPAddress: '#UserIPAddress'
}
};
var defaultConfig2 = {
url: 'test2/:testId/:AccessDateTime',
params: { testId: '#_id',
AccessDateTime:'#AccessDateTime'
}
};
function mod1(arg) {
var obj = defaultConfig1;
//modify config
return obj;
};
function mod2(arg) {
//modify and return defaultConfig
};
return {
resource1: $resource(defaultConfig1),
resource2: $resource(defaultConfig2).
modified1: function (arg) {
return $resource(mod1(arg));
},
modified2: function (arg) {
return $resource(mod2(arg));
}
}
}
]);
You have the full power of JavaScript to modify the configuration objects as you please before returning them.

ngResource search google news, but return results: Array[0]

sample code as follow,Is it about hl?locale? Many thanks.
.factory('newsResource', ['$resource', function($resource) {
return $resource('http://ajax.googleapis.com/ajax/services/search/news?v=1.0&q=%E6%96%B0%E8%81%9E');
}])
newsResource.get(
function(successResponse){
console.log(successResponse);
}
);
You have to use JSONP when making a request to an external domain and it seems the googleapis also support the JSONP.
You could change your $resource to use JSONP instead like this:
.factory('newsResource', function($resource) {
return $resource('http://ajax.googleapis.com/ajax/services/search/news?v=1.0&q=%E6%96%B0%E8%81%9E', {}, {
get: {
method: 'JSONP',
params: { callback: 'JSON_CALLBACK' }
}
});
});
Example Plunker: http://plnkr.co/edit/jCDqCErP9UKLWuhBOtp4?p=preview

Service for YouTube oEmbed

I'm trying to create a Service in Angularjs to make use of various oEmbed providers including YouTube.
...
myServices.factory('YouTubeService', function ($resource) {
//how can I make the URL part dynamic?
return $resource('http://www.youtube.com/oembed/', {}, {
query: { method: 'GET', isArray: true },
})
});
...
The oEmbed URL structure is http://www.youtube.com/oembed?url=<url_of_video>
How can I make this service work with any YouTube URL provided by the user? In other words, can I call this Service from my Controller and pass in the URL in some way?
YouTubeService.query(<url here maybe>)
Here you go, this should work, I think.
myServices.factory('YouTubeService', function ($resource) {
var youtubeservice = {};
youtubeservice.query = function(urlProvided){
return $resource('http://www.youtube.com/oembed?url=:urlProvided', {}, {
query: { method: 'GET', isArray: true },
});
}
return youtubeservice;
});
Invoke:
YouTubeService.query(<url here>)
I am not sure if you can access external url like this(may throw cross domain error)
But for your question, why don't you use a service instead of factory like this
myServices.service('YouTubeService', function ($resource) {
//how can I make the URL part dynamic?
this.getStuff = function(url){
return $resource(url, {}, {
query: { method: 'GET', isArray: true },
}).query();
}
});
And invoke it like
YouTubeService.getStuff (dynamicUrl);

"Suggest slug name" API call in ngResource in AngularJS/Express app

I want the user to be able to set the slug name (URL) for a document in my app, but also I need some control so users don't override each other. It needs to be a separate call (not integrated with create/update) so the user can get visual feedback on their own slug name suggestions.
Therefore I've created a suggestSlug API call that takes an optional slug parameter as seed for the final slug name.
This is what my Express routes looks like:
app.get('/api/projects/suggestSlug/:slug', projects.suggestSlug);
app.get('/api/projects/suggestSlug', projects.suggestSlug);
app.get('/api/projects', projects.list);
app.get('/api/projects/:id', projects.show);
Now, I want to extend ngResource on the client side (AngularJS) to make use of this API:
angular.module('myapp.common').factory("projectModel", function ($resource) {
return $resource(
"/api/projects/:id",
{ id: "#id" },
{
update: { method: "PUT", params: { id: '#_id' } },
del: { method: "DELETE", params: { id: '#_id' } }
}
);
});
How do I extend the ngResource client to use my new API?
This was my solution: adding a separate $http-based method to my projectModel:
angular.module('myapp.common').factory("projectModel", function ($resource, $http) {
var projectModel = $resource(
"/api/projects/:id",
{ id: "#id" },
{
update: { method: "PUT", params: { id: '#_id' } },
del: { method: "DELETE", params: { id: '#_id' } }
}
);
projectModel.suggestSlug = function (slugSuggestion, callback) {
$http.get(
'/api/projects/suggestSlug/' + slugSuggestion
).success(callback).error(function(error) {
console.log('suggestSlug error:', error);
});
};
return projectModel;
});

Angularjs: a Service that serves multiple $resource urls / data sources?

I have an Angular service/provider that serves json data to my controller which works great:
angular.module('myApp.services', ['ngResource']).
factory("statesProvider", function($resource){
return $resource('../data/states.json', {}, {
query: {method: 'GET', params: {}, isArray: false}
});
});
But I also need to serve json data to the same controller from another file counties.json.
Where can I find out how to I write a service that serves both files to my controller?
You can update service to return a hash of resources, not a single one:
angular.module('myApp.services', ['ngResource']).
factory("geoProvider", function($resource) {
return {
states: $resource('../data/states.json', {}, {
query: { method: 'GET', params: {}, isArray: false }
}),
countries: $resource('../data/countries.json', {}, {
query: { method: 'GET', params: {}, isArray: false }
})
};
});
You will be able to use it adding .query() at the end your function name i.e. geoProvider.states.query() and geoProvider.countries.query() and myApp.services has to be injected into your controller, then inject geoProvider service into controller itself as well.
I'm assuming you want to execute some code when both files have loaded. Promises work really well for this. I don't think resources return promises, but you can use the $http service for simple ajax calls.
Here I define one service each for the two data files, and a third service that returns a promise that gets fulfilled when both files are done loading.
factory('states',function($http) {
return $http.get('../data/states.json');
}).
factory('countries',function($http) {
return $http.get('../data/countries.json');
}).
factory('statesAndCountries', function($q, states, countries) {
return $q.all([states, countries]);
});
Then in your controller:
statesAndCountries.then(function(data) {
var stateData = data[0];
var countryData = data[1];
// do stuff with stateData and countryData here
});

Resources