How can I access the dynamic navParams using the fluxible-router
For instance if I have a user component and I want to set the userId prop of the component based on the route
// configs/routes.js
module.exports = {
home: {
method: 'GET',
path: '/',
handler: require('../components/Home.jsx'),
// Executed on route match
action: require('../actions/loadHome')
},
user: {
method: 'GET',
path: '/user/:id',
handler: require('../components/User.jsx')
}
};
https://github.com/yahoo/fluxible-router/blob/master/docs/quick-start.md
How can I access that userId in the User.jsx component?
I assume you're using the fluxible-router here, generated apps usually do.
Every router call includes a Payload parameter:
module.exports = {
user: {
method: 'GET',
path: '/user/:id',
handler: require('../components/Home.jsx'),
action: function(context, payload, done) {
console.log( payload.toJS() );
context.executeAction(registerCollector, payload, done);
done();
}
}
};
More on where this parameter is created in the docs. But that parameter contains all your URL-parameters as a JSON object.
To access them you have to use the payload.toJS() function though. Which took me quite a while to find, since it's not emphasised in the docs.
To access them directly in the Component, use the handleRoute API.
That should solve your problem.
Related
I'm using angular resource with different entities and I have to call, for each of these entities, some custom methods with custom urls.
For example:
var actions = {
create: {
method: 'POST'
},
customMethod: {
method: 'PUT',
url: '/api/entity1/:id/custom',
params: {
id: '#id'
},
}
}
$resource('/api/entity1/:id', null, actions);
$resource('/api/entity2/:id', null, actions);
$resource('/api/entity3/:id', null, actions);
In this way, obviusly, customMethod will work only on entity1 because the url is not generic.
How can I create a custom action without defining urls, as I did on create action?
Thanks
you can use multiple variables when using $resource. replace
url: '/api/entity1/:id/custom'
with
url: '/api/:entity/:id/custom'
and use the appropriate params when calling the $resource function.
Add an action param for custom method and url:
var actions = {
create: {
method: 'POST'
},
customMethod: {
method: 'PUT',
params: { action: 'custom' },
}
}
$resource('/api/entity1/:id/:action', null, actions);
$resource('/api/entity2/:id/:action', null, actions);
I'm trying to set 2 different POST methods for one service like this:
angular.module('admin').factory('Cards', ['$resource',
function ($resource) {
return {
admin:
$resource('api/admin/cards/:cardId', {
cardId: '#_id'
}, {
update: {
method: 'PUT'
}
}),
user:
$resource('api/user/cards/:cardUserId', {
cardUserId: '#id'
}, {
add: {
method: 'POST'
}
})
};
}
]);
Part of server routes:
app.post('/api/get/cards', card.add);
And I'm trying to access it:
card.user.$add()
card.user.add()
card.add()
card.$add()
And nothing works...
Your route in express does not match that of either resources, in other words '/api/get/cards' !== 'api/admin/cards'.
If you log the request url in express, it should be easy to find the mismatches. Something like console.log(req.originalUrl).
I've got a problem with service configuration. I want to display one user by this function:
$scope.findOne = function() {
$scope.user = Users.get({
userId: $stateParams.userId
});
};
But I am in trouble with User service :( I don't know, how should I change my the code to avoid angular error:
Error in resource configuration for action object. Expected response
to contain an array but got an {2}
Here is a code of my actual working service (without function findOne working of course:))
'use strict';
angular.module('users').factory('Users', ['$resource',
function($resource) {
return $resource('users', {}, {
update: {
method: 'PUT'
},
remove: {
method: 'DELETE',
url: 'users/:id',
params: {id: '#_id'}
}
});
}
]);
At a guess, I'd say your users API endpoint is expecting /users/:userId for GET requests. Your code at the moment will request /users?userId=nnn. You need to add an action for get with the ID in the URL, eg
return $resource('users', {id: '#userId'}, {
get: {
method: 'GET',
url: 'users/:id',
isArray: false
},
// etc
You can also make users/:id the default URL as long as it doesn't interfere with your other action configurations.
Here's my resource:
.factory('Posting', ['$resource', function ($resource) {
return $resource('api/Postings/:action/:arg', {}, {
findByParent: { method: 'GET', params: { action: 'parent', arg: '#guid' }, isArray: true },
findByReference: { method: 'GET', params: { action: 'reference', arg: '#reference' }, isArray: true }
});
}]);
In my controller I'm using my resource as this:
Posting.findByParent({ guid: parent_guid },
function (success) {
...
},
function (error) {
...
});
This returns the URL /parent?guid=0ff646e9-4397-4654-b8d2-118c6258023a
However, using my resource like this:
Posting.findByParent({ arg: parent_guid },
function (success) {
...
},
function (error) {
...
});
Gives me the correct URL: /parent/0ff646e9-4397-4654-b8d2-118c6258023a
I thought the point with using an '#' was to give parameters better names?
I'm also wondering if I still should use $resource even tho my API isn't really RESTful.
Is it better to give my custom (unRESTful) functions their own URL? Something like:
findByParent: { method: 'GET', url: 'api/Postings/parent/:guid', params { guid: '#guid' }, isArray:true }
By default, if you define a parameter on the path (like you did with arg), and you pass in an object that has a matching key, like in the second example, that key will be used to resolve the path.
If however, there are no matching parameter, the keys of the object passed in will resolve to query parameters, like in the first example.
To set custom default resolves, you need to specify them in the second argument to resource, like this:
.factory('Posting', ['$resource', function ($resource) {
return $resource('api/Postings/:action/:arg',
{
action: '#action',
arg: '#guid'
},
{
findByParent: { method: 'GET', params: { action: 'parent' }, isArray: true },
findByReference: { method: 'GET', params: { action: 'reference' }, isArray: true }
});
}]);
This should make action resolve to what is specified in findByParent and findByReference, and arg to whatever value is passed in for key guid.
You could experiment with setting an # in the respective methods 'guid' property, but for your usecase, it does not seem to be necessary.
to answer your second question: you can specify several parameter controllers on a single path element (level). The only condition is that you don't use / specify resolutions for more than one of them in a single method. That is, you could do api/Postings/:action:anotherController/:arg, as long as you would specify resolutions for :action and :anotherController in separate methods.
Please find this awesome post by Ben Nadel http://www.bennadel.com/blog/2433-using-restful-controllers-in-an-angularjs-resource.htm with an example use
My rest api accpets DELETE requests to the following url
/api/users/{slug}
So by sending delete to a specified user (slug) the user would be deleted. here is the service code:
angular.module('UserService',['ngResource']).factory('User', function($resource){
var User = $resource('/api/users/:id1/:action/:id2', //add param to the url
{},
{
delete_user: {
method: 'DELETE',
params: {
id1:"#id"
}
},
update: {
method: 'PUT',
params: {
id1:"#id"
}
}
});
return User;
});
I call the delete function via
user.$delete_user({id:user.id}, function(){}, function(response){});
However the request seems to be send to the wrong url.
/api/users?id=4
So the parameter is actually missing, as a result I get a 405 Method not allowed. Is there any chance to send the delete request in the style of my api?
params is an object of default request parameteres in your actions. If you want url parameters you have to specify them in the second parameter like this:
angular.module('UserService',['ngResource']).factory('User', function($resource){
var User = $resource('/api/users/:id1/:action/:id2', //add param to the url
{id1:'#id'},
{
delete_user: {
method: 'DELETE'
}
});
return User;
});
this works with either:
// user has id
user.$delete_user(function(){
//success
},function(){
// error
});
or
var data = {id:'id_from_data'};
User.delete_user({},data);
or
var params = {id1:'id1_from_params'};
User.delete_user(params);
I've made a plnkr-example - you have to open your console to verify that the DELETE requests are correct.
See parameterDefaults in the Angular resource documentation.
I had this problem for a while I was using a service to add / delete / update categories. While passing in params for get it worked fine but then when deleting it was giving me a ?id=1234 instead of api/resource/1234
I got around this by making the default param a string.
///Controller
Service.delete({categoryId:id}, function(resp){
console.log(resp)//whatever logic you want in here
});
//SERVICES
$resource('api/resource/:categoryId', {"categoryId":"#categoryId"}, {
query:{method:"GET"},
delete:{method:"DELETE"},
});
Should work and the resulting url will be, originally I had categoryId in the default params as a variable name.
api/resource/1234 etc
Just omit the '#' in the parameter
.factory('reportFactory', ['$resource', 'baseUrl', function ($resource, baseUrl) {
return $resource(baseUrl + '/keys/:id', {}, {
delete: { method: 'DELETE',
headers: {
'Content-Type': 'application/json'
},
params: {id: 'id'} }
})
}]);
this will give you:
http://localhost:8080/reports/api/keys/b8a8a8e39a8f55da94fdbe6c
without the question mark
If you want to delete a model, there's no need to add params (params does not work for DELETE anyway):
$resource('/users/:id').delete({id: user.id}, function(res) {
...
})
or
$resource('/users/:role/:id').delete({role: 'visitor', id: user.id});
I'm not sure if it's a bug of ngResource.