Url issues in nodejs search and pagination - javascript

I have a results page with pagination. Routes are as follows:
app.get("/results",function(req,res){
query= select * from courses where
// the following line adds search parameters from req.query to the sql query//
Object.keys(req.query.search).forEach(function(key){
query+= key + " = "+ (req.query.search[key])
})
conn.query(query,callback(){
....
....
...
res.render("results",{results,results})
})
)}
This code works fine at first but as soon as I click pagination buttons to move to second page , the search_query parameters do not pass to second page and req.query.search becomes undefined there for sending undefined results error.
Anyone?

It seems that your method does not send the search_query parameter but you can try this so you do not have problems with undefined.
app.get("/results/:id", function (req, res) {
const { id } = req.params;
// Now in this part you can use the value of the variable id for your query
// Implementing my amazing query...
});
¿What is the difference?
Using this form we ensure we have a value that we can use for the page, so now our requests will be for example http://localhost/results/14 where 14 can be my id that I use as a filter in the query.

Related

Object of which I have a working method for is somehow undefined? Javascript app.patch request [duplicate]

I am trying to create two routes in my express app. One route, without a parameter will give me a list of choices, the other one with a parameter will give me the choice related to the id.
router.get('/api/choice', choice_controller.get_choices);
router.get('/api/choice/:id', choice_controller.get_choice);
When I go to .../api/choice/?id=1 the api returns the list of choices, and therefore follows the route without the param (/api/choice). How do I make sure that the router does not omit the parameter?
Thanks in advance.
UPDATE
It seems that it does not fire the /api/choice/:id route. If I remove the one without the param, it gives a 404 so. Could someone explain to me why /api/choice/?id=1 is not getting picked up by /api/choice/:id?
Basically, your declared routes are documented in the Express documentation.
The second route is resolved by a URL like /api/choice/hello where 'hello' is mapped into the req object object as:
router.get('/api/choice/:id', function (req, res) {
console.log("choice id is " + req.params.id);
});
What you are actually trying is mapping query parameters.
A URL like /api/choice/?id=1 is resolved by the first router you provided.
Query parameters are easy to get mapped against the request as:
router.get('/api/choice', function (req, res) {
console.log('id: ' + req.query.id);
//get the whole query as!
const queryStuff = JSON.stringify(req.query);
console.log(queryStuff)
});

How to get only one user instead of a list?

I try to get from a list of users to only one user and display his profile on another page.
I want to do so with the routerLink and passing on an id of this specific user to the next page.
The routing is working, Im directed to the profile page but when I log the results of the http request I still get back the whole list of users like in the users page instead of the details of one user.
I have tried many things like changing the path of the url in my user.service.ts but that didn't solve the problem I even got 404 request errors when using this path ${this.url}/users/${id}/ instead of ${this.url}/users/?i=${id}/ (where its working).
The api docs is saying though that in order to retrieve one single user its http://1234//users/{id}/ it this scheme while id is an integer. But when I want to apply that scheme I get the 404 error.
Thats why I have to use the ?I= version but there the problem is I only get the full list of users on the next page.
MY CODE:
user.service.ts
// get a user's profile
getUserDetails(id): Observable<any> {
return this.http.get(`${this.url}/users/?i=${id}/`); // why add ?i
}
user.page.ts
// get all users in the users page
getAllUsers() {
this.userList = this.userService.getList()
.pipe(map(response => response.results));
}
user.page.html
<ion-avatar class="user-image" slot="start" [routerLink]="['/','profile', 'user.id']">
<ion-img src="assets/22.jpeg"> </ion-img>
</ion-avatar>
profile.page.ts
information = null;
...
ngOnInit() {
// Get the ID that was passed with the URL
let id = this.activatedRoute.snapshot.paramMap.get('id');
// Get the information from the API
this.userService.getUserDetails(id).subscribe(result => {
this.information = result;
console.log(result);
});
}
It seems like the url is wrong. If it was me I would console.log the url and compare it to the docs. Heres a snippet to try a few variations:
const id = 1;
const options = [
`${this.url}/users/?i=${id}/`,
`${this.url}/users/?i=${id}`,
`${this.url}/users/i/${id}/`,
`${this.url}/users/i/${id}`,
`${this.url}/user/?i=${id}/`,
`${this.url}/user/?i=${id}`,
`${this.url}/user/i/${id}/`,
`${this.url}/user/i/${id}`,
];
for (const option of options) {
try {
const response = await this.http.get(option);
console.log(options, response);
} catch (e) {
}
}
I would also consider dropping the second http request. If the first request returns all the required data you could just store it in a variable on the service.

How to clear the search parameter that caused the error?

Let's say I have a page that renders search results depending on the parameters in the URL like so:
https://www.someurl.com/categories/somecategory?brands=brand1,brand2,brand3
Which results in the page showing only brand1, brand2, and brand3 listings. I also have a filter section on the side like so:
[o] Brand 1
[ ] Brand 2
[o] Brand 3
[o] Brand 4
By ticking the items, the URL will get updated with the corresponding parameters. Basically, what happens is that I am fetching data from an API by passing the URL parameters as arguments, which then the server side endpoint takes in to return to me the matching data.
Now the problem is that, if a user types into the URL an invalid parameter e.g.
https://www.someurl.com/categories/somecategory?brands=somegibberish
The server will return an error (which I then display on the page).
However, when I tick one or more of the filters, since what it does is merely append into the URL more parameters, the server will always return an error as the errant parameter is still being sent over:
https://www.someurl.com/categories/somecategory?brands=somegibberish,brand1,brand2
To solve this, currently, when someone clicks a filter and error is not null, I just clear the parameters like so:
componentDidUpdate(prevProps)
if (prevProps.location.search !== location.search) {
if (
someobject.error &&
!someobject.list.length
) {
this.props.history.replace("categories", null);
this.props.resetError();
}
}
}
Which results in the path becoming:
https://www.someurl.com/categories/
But the UX of that isn't smooth because when I click a filter (even if there was an error), I expect it to do a filter and not to clear everything. Means if I have this path previously (has an error param):
https://www.someurl.com/categories/somecategory?brands=somegibberish,brand1
..and I click on brand2 in my filters, the path should become:
https://www.someurl.com/categories/somecategory?brands=brand1,brand2
But am quite stumped as to how to know which of the parameters has to be removed. Any ideas on how to achieve it? Should the server return to me the 'id' that it cannot recognize then I do a filter? Currently, all the server returns to me is an error message.
I agree with SrThompson's comment to not support typing of brands in the app since anything outside of your list results in an error anyway.
Expose an interface with the possible brands for the user to make a selection from.
With that said, here's how you can go about filtering the brands in the request URL.
Convert the URLstring to a URL object and retrieve the value for "brands" query parameter from its search params.
const url = new URL(
"https://www.someurl.com/categories/somecategory?brands=somegibberish,brand1,brand2")
const brands = url.searchParams.get("brands")
Filter brands that are not included in the filter list
const BRAND_FILTER = ['brand1', 'brand2']
const allowedBrands = brands.split(',')
.filter(brand => BRAND_FILTER.includes(brand))
.join(',')
Update the brand query parameter value
url.searchParams.set("brands", allowedBrands)
Then get the URL to be used for the request.
const requestURL = url.toString();

Express get URL and delete certain object

Now I'm developing CRUD(Create, Read, Update, Delete) App with Express and LowDB.
And I successfully developed the create and read but Delete Function is not working.
There are detail page like this
as you can see there are trash can Icon and actually I also have some problem the submit button but It's not important so I just make submit button.
this is the part of the pug file
aside#Delete.is-visible
form(method="post" action='/delete_process')
input(type='submit')
a#DeleteButton(role='button')
img(src='https://png.icons8.com/ios/35/000000/waste-filled.png' id="go_up")
span.text
| Delete
br
b this
detail page have URL (ex: DIR1WTqr2) and it's DB id
and delete Process code is like this.
/* Delete Process */
router.post('/delete_process', function (req, res) {
// GET Delete ID from URL
let id=req.params.id;
console.log(id);
db.get('project').find({
id: id
}).remove().write();
});
I thought I can get URL and find the data with the id in json file. but It's not working. When I tried to console the req.params.id it said undefined
And I think there are collision with view Detail page because Detail page code is like this.
/* GET Detail View Page */
router.get('/:id', (req, res, next) => {
// GET URL params and put it into :id
let id = req.params.id;
// console.log(id);
// GET data id to use Object
let data = db.get('project').find({
id: id
}).value();
// Get github URL
let url = data.githuburl;
// Use Request Module to parsing Web page
request(url, function (error, response, html) {
if (error) {
throw error
};
// Parsing readme ID in github page
var $ = cheerio.load(html);
$('#readme').each(function () {
// save to readme Variable
let readme = $(this).html();
// console.log(data);
// console.log(id);
res.render('detail', {
dataarray: data,
name: data.name,
url: data.url,
explanation: data.explanation,
imgurl: data.imgurl,
markdown: readme,
startDate: data.pjdate1,
endDate: data.pjdate2,
githuburl: data.githuburl,
sumlang: data.sumlang
});
});
});
});
because of :id when I click the /delete_process it goes to detail page I think.
Pug is very specific about your indentation. Your button wasn't contained inside the form - it was a sibling. Make sure that you've always got two spaces when you want an element to be contained inside another.
Change the pug template to this and the button will submit properly:
aside#Delete.is-visible
form(method="post" action='/delete_process')
input(type='submit')
a#DeleteButton(role='button')
img(src='https://png.icons8.com/ios/35/000000/waste-filled.png' id="go_up")
span.text
| Delete
br
b this
But wait there's more! You aren't passing the id of the restaurant back with the form.
I can't see how you're using the restaurant id in the pug, but you'll need to add that into the form somehow too. Let's assume it's a variable in the pug template called restaurant.id.
Your node.js route handler is trying to read req.params.id which means that it's going to look to the url to get the id of the restaurant. You can add the id to the request like this:
aside#Delete.is-visible
form(method="post" action='/delete_process/' + restaurant.id)
input(type='submit')
Then, you'll also need to modify your route to include the id parameter:
router.post('/delete_process/:id', function (req, res) {
A different way to do this would be to add a hidden form field that sends the id with the form (here's an article that explains this concept). If you do it this way you can change the form to look like this:
aside#Delete.is-visible
form(method="post" action='/delete_process/' + restaurant.id)
input(type='hidden' name='id' value= restaurant.id)
input(type='submit')
Then your delete handling route can pick it up like this:
router.post('/delete_process', function (req, res) {
// GET Delete ID from form field
let id= req.body.id;
The first method of passing the id (in the url) is standard for ajax requests, the second method (as a field in the form) is the standard for posting a form.

Parse - limit result of a Query in Cloud Code

Hello is this code in the comment possible with Parse Cloud Code?
Parse.Cloud.beforeFind('Note', function(req) {
var query = req.query;
var user = req.user;
// if a given 'Note' visibility is set to 'Unlisted'
// return only the Notes with 'user' field that the calling _User
});
The documentation only shows how to filter fields that are returned but not exactly remove items from the query result in the Cloud Code.
This can be done through ACL, I know, but the caveat is that if the request is a retrieve function and not query the Note should still return.
Assuming you've saved the user as an object relationship (not a string id). Just add the qualification you need, such as:
query.equalTo("your_user_pointer_col_on_Note", user)

Categories