Mohamed Mohamed - 4 months ago 8
AngularJS Question

Node.js multible get functions with different parameters

I have the following Node.js Express routes

app.get('/api/admin/elements/:type', elements.getElementsByType);
app.get('/api/admin/elements/:_id', elements.getElement);


the elements funtions are:

getElementsByType : function(req, res) {
element.find({
type : req.params.type
}, function(err, elements) {
if (err) {
return err;
}
res.json(elements);
});
},
getElement : function(req, res) {
var file = "/thatulborooj-data/elements/" + req.params._id + ".json";
jsonfile.readFile(file, function(err, obj) {
if (err) {
res.json([]);
} else {
res.json(JSON.parse(obj));
}
});
}


when I all
$http.get('/api/admin/elements/' + scope.element._id)
fro angularJS it always all the first get, how can I make difference between them or set parameter type

Answer

express.js doesn't know the name of the variable that you pass to it, because it is a webserver which listen to some addresses.

In your case the first route says:

If someone goes on /api/admin/elements/{{whatever}} call the function elements.getElementsByType() and assign whatever to the variable type

The second route says the same thing, just to call another function and assign the value to the var _id.

A possible solution is to have two different routes:

app.get('/api/admin/elements/type/:type', elements.getElementsByType);
app.get('/api/admin/elements/id/:_id', elements.getElement);

Another possible solution is, if you are sure id is always an int and type is never an int is to call just one function and choose what to do checking the param type:

app.get('/api/admin/elements/:value', elements.getElementsByType);

getElementsByType : function(req, res) {
if (isNaN(req.params.value)) {
  // this is a type
} else {
  //this is an id
}

But I want to highlight it is important you understand why your example doesn't work.

I cannot explain how web works in just one answer, but let me highlight some things:

express.js listens on your server to request to a port, as a webserver. You can say to express.js which routes you want to listen: all routes that aren't specified will reply with 404 (or 405 if you ask for a method that doesn't exist on a resource that exists, like POST on /api/admin/elements/{{whatever}} in your example).

So, when you specify a route, you have two components:

a fixed part, which is the address, and it is always the same (like /api/admin/elements/), and a part which value can change.

You say to express.js which part can change using the : notation. For express.js, whatever is in an URL between the /: and the next / has to be passed in the req.params object with the name you specify.

Let's do some examples:

/a/:a/b/:b/c/:c

This address will response to each call you do to `/a/{{param1}}/b/{{param2}}/c/{{param3}}

So you will have a req.params object with these 3 values:

req.param = {
  a: 'param1',
  b: 'param2',
  c: 'param3',
}

You do not like a, b, and c as names? Me neither, so let's change that:

/a/:artemis/b/:betelgeuse/c/:cassidy

Then the req.params object will be:

req.param = {
  artemis: 'param1',
  betelgeuse: 'param2',
  cassidy: 'param3',
}

But for express.js it is the same thing, it cannot choose what it is basing only on the value.

Now, an example a bit more complicated:

if you have

/a/:a and /a/b for express.js can be a bit confusing (but also for whoever uses your APIs, so please do not do this).

Now, how this works is up to the order you declared the routes.

If you did /a/:a and then /a/b the function associated to /a/b will never be called. express.js takes the address requested and check each route if it has a match. So if you call /a/b express.js finds /a/:a (that means an /a/ and a thing after this and thinks the b is a valid value for the variable a).

But if you declare the /a/b before the /a/:a express.js will reach before the /a/b (that means a route that is exactly /a/b) then it will be matched first.