Angular-Fullstack: Using $resourse query with params - javascript

I'm using Angular-Fullstack generator, and I'm not able to get a list of drivers depending on a companyID, through $resource query. This is what I have:
server/api/driver/index.js:
router.get('/:company', controller.index);
server/api/driver/driver.controller.js:
export function index(req, res) {
return Driver.find({company: req.params.company}).exec()
.then(function(res){
console.log(res); /* I get here the result correctly */
respondWithResult(res)
})
.catch(handleError(res));
}
client/services/driver.service.js:
export function DriverResource($resource) {
'ngInject';
return $resource('/api/drivers/:id/:company', {company: '#_id'});
}
client/app/driver/driver.controller.js:
this.driverList = Driver.query({company: Auth.getCurrentUser()._id}});
console.log(this.driverList); /* Empty array */
I'd be grateful if someone could help me getting the response from the server...
Thank you in advance.

I just realised that I was duplicating the 'res' variable:
server/api/driver/driver.controller.js:
export function index(req, res) {
return Driver.find({company: req.params.company}).exec()
.then(function(**res**){
/* Should be the result, not the response */
console.log(**res**);
respondWithResult(**res**)
})
.catch(handleError(res));
}

You were close.
Driver.query({company: 'foo'}).$promise.then(function(results) {
console.log(results) //here
}, function(err) {
//here is your 404 error, but you should create an http interceptor
});
It's async, do you don't get your results right away.
This will work of course, assuming your backend responds properly.
EDIT: Your backend is missing some endpoints. You should be able to respond to requests to /api/drivers/ with a list of drivers
EDIT 2:
Angular's resource will give you access to some methods:
Driver.get(1) Will make a request to /api/drivers/:id and will be expecting the backend to respond with an object representing the driver with said ID. This should be used when you want to fetch only 1 record
Driver.query({foo: 'bar', some_id: 1}) Will make a request to /api/drivers?foo=bar&some_id=1 and will be expecting the backend to respond with an array of objects, each representing a driver. This should be used when you want to fetch several records, for example in an index.
Driver.query() will make a request to /api/drivers and will be expecting the backend to respond with an array
Driver.create(data) will make a POST request to /api/drivers and will expect an object (the created driver) in the response. Used to create a new record
There are some others, this is the ones I use.
So, your backend, considering you are using this three methods, needs to handle:
router.get('/drivers/:id', function(req, res) {
let id = req.params.id
})
router.get('/drivers', function(req, res) {
//if request was /drivers?foo=bar
let foo = req.query.foo
})
router.post('/drivers', function(req, res) {
let body = req.body
})
As I said, there are several things in play here. If you are at a lost, break the problem into pieces. Get the backend working before going to Angular.

Related

How to route through a path and perform different functionality at different URLs?

I would like to post at the path /users and then immediately post to /users/:id, but the actions need to be different at each of these URLs, so I can't use the array method for applying the same middleware to different URLs
The idea is that POST(/users/:id, ...) will never be called by the client. It only gets called immediately after POST(/users, ...)
When using express, you are providing a handler function for a specific endpoint. Actually it's an array of those functions (middlewares). That means that you can switch from :
route.post('/users/`, (req, res, next) => {
// do your magic
});
to
route.post('/users/', handleMyCall);
This way you can easily reuse those functions in multiple endpoints without your need to actually make requests:
route.post('/users/', (req, res) => {
// do something +
handleMyCall(req, res);
// either return the result of this call, or another result
});
route.post('/users/:userID', (req, res) => {
// do another operation +
handleMyCall(req, res);
});
Update:
Using GET or POST differs in the way the data is sent to the server. You can use both for your cases, and it really depends on the testing client you have.
Typically, a GET request is done to query the database and not do any actions. POST is usually used to create new entities in the database.
In your scenario, I'd guess you would have post('/users/) in order to create a user. And then have get('/users/:userID') to find that user and return it to the client.
You can easily have different endpoints with different handles for those cases.
As I understood from the comments, you'll need a POST request on /users (to persist data in some database) and GET /users/:id to retrieve these data, which is very different from POSTing the same thing on 2 different endpoints.
POST is generally used to persist and GET to retrieve data.
I'll assume you use some kind of NoSQL DB, perhaps MongoDB. MongoDB generate a unique ID for each document you persist in it.
So you'll have to have 2 routes :
const postUser = async (req, res, next) => {
try {
// persist your user here, perhaps with mongoose or native mongo driver
} catch (e) {
return next(e);
}
}
const getUserById = async (req, res, next) => {
try {
// get your user here thanks to the id, in req.params.id
} catch (e) {
return next(e);
}
}
export default (router) => {
router.route('/users').post(postUser);
router.route('/users/:id').get(getUserById);
};

Problem with React making Get request to Node(express)

As the title says, i have a part of my react app that tries to get some data from my database, making a select based on the value I passed to it. So im gonna go ahead and first show the code where i think the problem lies:
So first, this is the function from one of my forms that sends the request to the server, i know code is probably ugly, but i can tell from the console.logs that the parameters im sending are what i intend to send(a string called "licenciaInput"
async handleClickLicencia (event) {
event.preventDefault();
console.log(this.state);
console.log("licenciaInput: "+this.state.licenciaInput);
const datoBuscar = this.state.licenciaInput;
axios.get('http://localhost:3001/atletas/:licencia',this.state)
.then(response =>{
console.log(response)
})
.catch(error =>{
console.log(error)
})
And then, i have this function which is called in that localhost route which attempts to get "licencia", and launch a select in my postgresql db where licencia="whatever", you can see the sentence in the code:
const getAtletasByLicencia = (request, response) => {
const licencia = request.body.licenciaInput;
console.log("Request: "+request);
console.log("what the server gets: "+licencia);
// const licencia = request.licenciaInput;
const sentencia ="SELECT * FROM atleta WHERE licencia ='"+licencia+"'";
pool.query(sentencia, (error, results) =>{
if(error){
throw error
}
response.status(200).json(results.rows)
})
}
As you can see, i have console.logs everywhere, and i still cannot access whatever element i send, because i always get on the server console "undefined" value.
TLDR:How can i access the "licenciaInput" i passed from my client form to my server, i have tried request.body.licenciaInput, request.params.licenciaInput, and request.licenciaInput, but none of those seem to work
I also know i have to treat after that the data i receive from the server, but i need to solve this before looking two steps ahead. Im also really new to React and node/express, so feel free to burn me with good practices im not meeting.Thanks in advance
EDIT: Im also adding this code that i have which shows the route for my method in the server:
app.get('/atletas/:licencia', db.getAtletasByLicencia)
As #Gillespie59 suggested that i should send a POST request, but i dont think i should if im both trying to send a parameter to the server to make a select, and then send the results back to the client
Change your request to:
axios.get(`http://localhost:3001/atletas/${this.state.licenciaInput}`)
...
and your route (if you are using express) should look like this:
app.get('/atletas/:licencia', function (req, res) {
var licencia = req.params.licencia
...
})
As you are using request.body you should send a POST request with axios and add a body.

What is the best way to write a .find query in a GET request with mongodb?

I am trying to make a GET request so that it only returns the last item stored in my database. I can get the answer I want in the mongo shell (see below), but I'm at a loss as to how to compose the query in my GET route. I am using ejs templates, so I will also need to pass the response through the res.render as well. I am still kind of new to programming so forgive me if this question isn't as concise as it should be.
My mongo shell query:
Blog.find().sort({_id:-1}).limit(1)
I hope the code below gives you a hint on how to structure your code using express and EJS.
app.get("/", async (req, res) => {
try {
const blogItem = await Blog.find().sort({_id:-1}).limit(1);
// Render the page with the result
res.render("your-page.ejs", { blog: blogItem });
} catch (error) {
// Handle errors here
res.render("500.ejs");
throw error;
}
});

Node.js app receives empty response from GET request to API

I'm new to node.js so I'll try my best to explain the problem here. Let me know if any clerification is needed.
In my node.js application I'm trying to take a code (which was received from the response of the 1st call to an API), and use that a code to make a 2nd request(GET request) to another API service. The callback url of the 1st call is /pass. However I got an empty response from the service for this 2nd call.
My understanding is that after the call back from the 1st call, the function in app.get('/pass', function (req, res).. gets invoked and it sends a GET request. What am I doing wrong here? Many thanks in advance!
Here is the part where I try to make a GET request from node.js server and receive an empty response:
app.get('/pass', function (req, res){
var options = {
url: 'https://the url that I make GET request to',
method: 'GET',
headers: {
'authorization_code': code,
'Customer-Id':'someID',
'Customer-Secret':'somePassword'
}
};
request(options, function(err, res, body) {
console.log(res);
});
});
Im a little confused by what you are asking so ill just try to cover what i think you're looking for.
app.get('/pass', (req, res) => {
res.send("hello!"); // localhost:port/pass will return hello
})
Now, if you are trying to call a get request from the request library when the /pass endpoint is called things are still similar. First, i think you can remove the 'method' : 'GET' keys and values as they are not necessary. Now the code will be mostly the same as before except for the response.
app.get('/pass', (req, res) => {
var options = {
url: 'https://the url that I make GET request to',
headers: {
'authorization_code': code,
'Customer-Id':'someID',
'Customer-Secret':'somePassword'
}
};
request(options, function(err, res, body) {
// may need to JSONparse the body before sending depending on what is to be expected.
res.send(body); // this sends the data back
});
});

Node JS app only display the first JSON object. Why?

I am trying to write a json object in my node application, integrating the Twilio API. When console logging the object all objects are returned properly but when I write it to the document only the first object is written. Why? How should I change the code to see the same written response as in my console log.
var express = require('express');
var app = express();
app.use(express.bodyParser());
app.get('/', function(req, res) {
var accountSid = 'xxx';
var authToken = 'xxx';
var client = require('twilio')(accountSid, authToken);
client.messages.list({
from: "xxx",
to: "xxx"
}, function(err, data) {
data.messages.forEach(function(message) {
console.log(message.body); // THIS WILL DISPLAY ALL OBJECTS
res.json(message.body); // THIS WILL ONLY DISPLAY THE FIRST OBJECT
});
});
});
app.listen(1337);
I am new to Node JS and think this is easy to solve, but I still can’t find the solution.
res.json(...); sends back the response. You are doing that in the first iteration over the array, hence the client only gets the first message.
If you want to extract body from all messages and send all of them back, then do that. Create an array with the data you want and send it back. Example:
res.json(data.messages.map(function(message) {
return message.body;
}));
You can only call res.json once per request. You're calling it multiple times in a loop. The first time you call it, the browser receives the response, and you'll get a headers already sent exceptions (or something like that) for all other res.json calls.
res.json actually does a data conversion to JSON. I'd be willing to bet there is something it is not dealing with, or it's simply screwing it up. If the response from Twilio is already json, you probably don't need to do that. Try res.send, instead, which just returns whatever you got back.

Categories