How to create a ajax POST with node JS? - javascript

I am not sure how to use an ajax POST to POST from a Jade Page to Node JS. If someone can provide an example or tell me what I am missing from the script I have, please let me know.
This is the script file:
//Add friends
$('.addContact').click(function() {
$.post('/addContact',
{friendRequest: $(this).data('user')});
if($(this).html!=='Contact Requested') {
return $(this).html('Contact Requested');
}
});
The url I have for a POST on my app.js file is:
app.post('/addContact', user.addContactPost);
I am trying to post true for a click event on the button Add Contact and change it to Contact Requested if the data in the db is shown as true.
This is the jade file:
extends layout
block content
div
legend Search Results
div#userResults
for user in ufirstName
a(href='/user/#{user.id}')
p #{user.firstName} #{user.lastName}
button.addContact Add Contact
The route file is this:
exports.addContactPost = function(req, res, err) {
User.findByIdAndUpdate(req.signedCookies.userid, {
$push: {friendRequest: req.body.friendRequest}
}, function(err) {
if(err) {
console.log("post2");
return console.log('error');
//return res.render('addContactError', {title: 'Weblio'});
}
else {
console.log('postsuccess');
//alert('Contact added');
res.json({response: true});
}
});
};

If you are posting AJAX request, then you are expecting from JS on client-side to get some response, and react to this response accordingly.
If it would be separate request to another page - then probably rendering whole page - would be actual option.
But as you just need to get response from server and then update your front-end without reloading based on response, then you need to response from server on this POST request with some JSON. And then on client-side, do some templating, use jQuery or some templating libraries on client side for it.

Everything looks good I just think the $.post code is a little off. This might fix your problem.
$('.addContact').click(function() {
$.post('/addContact', { addContact : true }, function(data){
console.log('posting...');
$('.addContact').html(data);
});
...
});
The object I added to the $.post is what is going to be sent to the server. The function you specified at the end is your callback. It's going to be called when the function returns. I think that may have been some of your confusion.
Your node route should look something like this
exports.addContactPost = function(req, res, err) {
User.findByIdAndUpdate(req.signedCookies.userid,{
addContact: req.body.addContact
}, function(err) {
if(err) {
console.log("post2");
res.render('addContactError', {title: 'Weblio'});
}
//assuming express return a json object to update your button
res.json({ response : true });
});
};

Related

How do I search for a data in the database with Node JS, Postgres, and dust js

I'm making a webpage with Node JS with dustjs and PostgreSQL. How do I make a search query in the html, so I can pass the value to the app.get
Do I need to use JQuery?
app.get('/teachers', function(req, res){
pool.connect(function(err, client, done){
if(err) {
return console.error("error", err);
}
client.query('SELECT * FROM teachers', function(err, result){
if(err){
return console.error('error running query', err)
}
res.render('teacherindex', {teachers: result.rows});
done();
});
});
});
app.get('/teachers/:str', (req,res)=>{
pool.connect((err, client, done) => {
if (err) throw err
client.query('SELECT * FROM teachers WHERE name = $1', [req.query.namesearch], (err, result) => {
done()
if (err) {
console.log(err.stack)
} else {
res.render('teacherindex', {teachers: result.rows});
}
})
})
})
This is my JQuery
$("#myBtn").click(function(){
var str = $("#myInput").val();
var url = '/teachers/'+str;
if(confirm('Search Record?')){
$.ajax({
url: url,
type: 'put',
success: function(result){
console.log('Searching');
window.location.href='/teachers';
},
error: function(err){
console.log(err);
}
});
}
});
My HTML
<input type="text" id="myInput" data-id="namesearch">
<button type="button" id="myBtn">Show Value</button>
Thank you!
FINAL ANSWER:
Ok so it turns out the issue you were having was something completely different. You are trying to use server side rendering for this, and I was showing you how to render the retrieved data on the client side.
I have forked, and updated your repo - which can be found at the link below..
Please review my changes and let me know if you have any questions.
Working repo: https://github.com/oze4/hanstanawi.github.io
Demo Video: https://raw.githubusercontent.com/oze4/hanstanawi.github.io/master/fake_uni_demo.mp4
EDIT:
I went ahead and built a repository to try and help you grasp these concepts. You can find the repo here - I tried to keep things as simple and understandable as possible, but let me know if you have any questions.
I had to make some minor changes to the paths, which I have commented explanations on the code in the repo.
I am using a "mock" database (just a JSON object in a different file) but the logic remains the same.
The index.js is the main entry point and contains all route data.
The index.html file is what gets sent to the user, and is the main HTML file, which contains the jQuery code.
If you download/fork/test out the code in that repo, open up your browsers developer tools, go to the network tab, and check out the differences.
Using req.params
Using req.query
ORIGINAL ANSWER:
So there are a couple of things wrong with your code and why you are unable to see the value of the textbox server side.
You are sending a PUT request but your server is expecting a GET request
You are looking for the value in req.query when you should be looking for it in req.params
You are looking for the incorrect variable name in your route (on top of using query when you should be using params) req.query.namesearch needs to be req.params.str
See here for more on req.query vs req.params
More detailed examples below.
In your route you are specifying app.get - in other words, you are expecting a GET request to be sent to your server.. but your are sending a PUT request..
If you were sending your AJAX to your server by using something like /teachers?str=someName then you would use req.query.str - or if you wanted to use namesearch you would do: /teachers?namesearch=someName and then to get the value: req.query.namesearch
If you send your AJAX to your server by using the something like /teachers/someName then you should be using req.params.str
// ||
// \/ Server is expecting a GET request
app.get('/teachers/:str', (req, res) => {
// GET THE CORRECT VALUE
let namesearch = req.params.str;
pool.connect((err, client, done) => {
// ... other code here
client.query(
'SELECT * FROM teachers WHERE name = $1',
// SPECIFY THE CORRECT VALUE
namesearch,
(err, result) => {
// ... other code here
})
})
});
But in your AJAX request, you are specifying PUT.. (should be GET)
By default, AJAX will send GET requests, so you really don't have to specify any type here, but I personally like to specify GET in type, just for the sake of brevity - just more succinct in my opinion.
Again, specifying GET in type is not needed since AJAX sends GET by default, specifying GET in type is a matter of preference.
$("#myBtn").click(function () {
// ... other code here
let textboxValue = $("#myTextbox").val();
let theURL = "/teachers/" + textboxValue;
// OR if you wanted to use `req.query.str` server side
// let theURL = "/teachers?str=" + textboxValue;
if (confirm('Search Record?')) {
$.ajax({
url: theURL,
// ||
// \/ You are sending a PUT request, not a GET request
type: 'put', // EITHER CHANGE THIS TO GET OR JUST REMOVE type
// ... other code here
});
}
});
It appears you are grabbing the value correctly from the textbox, you just need to make sure your server is accepting the same type that you are sending.

How do I display response data in the front end?

I've made GET requests to the github API:
axios.get('https://api.github.com/users/roadtocode822')
.then(function (response) {
console.log(response.data);
})
I get the response data. This function lives in the app.js file.
Also lives on the app.js file is the following code:
app.get('/', function(req, res){
Article.find({}, function(err, articles){
if(err){
console.log(err);
} else {
res.render('index', {
title: "Articles",
articles: articles
});
}
});
});
I'm able to query data from my mongodb database through the Article.js mongoose model and send the data to my index.pug file.
I want to be able to take the GITHUB response data and also render it in one of my pug view files. I feel like I'm missing some sort of concept in Javascript that's preventing me from achieving this.
Thanks in advance.
To get the Github response as a JSON, just use JSON.parse(). You won't be able to use your .pug template on the front end, however. That template is interpreted on the server side and is sent from server to client as plain old HTML. If you're interested in front-end templating, check out something like handlebars.js.
axios.get('https://api.github.com/users/roadtocode822')
.then(function (response) {
console.log(response.data);
})
from the code above, response.data will be a html content because your server returns res.render.
in the front-end, you should use a tag and form post instead of ajax call like this
Click

Stormpath Custom Data

I requested stormpath user custom data by using
res.render('home', {
title: 'home',
user: req.user.customData,
});
i expected to receive a json object of custom data but instead a url ('https://api.stormpath.com/v1/accounts/WvtGbIH3kJ4rEttVF5r9U/customData') was returned. This page does have the custom data i want on it but i cannot request it using an ajax request as it is a https page. What should I do? Thanks in advance
You'll need to use the "auto expansion" feature of the library, like this:
app.use(stormpath.init(app, {
expandCustomData: true,
});
That will expand the custom data resource for you. By default it's just a link to the resource, as you've seen.
Found the best way to request custom data is to use the getCustomData() method in the route, set the data to a variable and use a get request from the client to request this data as in the sample below:
Server Js
customData = new Array;
router.get("/string", function(req, res) {
req.user.getCustomData(function(err, data) {
customData = data.someKey;
})
res.send(customData) /*Returns Empty Arrray*/
})
router.get("/cdata", function(req, res) {
res.send(customData) /*Sends Actual Custom Data*/
})
Client Js
var customData = new array
$(document).ready(function() {
$.get("/string", function(string) {
/*Tells server to get customData*/
})
$(document).click(function(){
if(pleaseCount===0){
$.get("/cdata", function(data) {
for(i=0;i<data.length;i++){
customData.unshift(data[i])
pleaseCount=pleaseCount+1
/*Custom data is now stored in client side array*/
}
})
}
})
That's what worked for me anyway. I don't know why someone down-voted the question as this is an acceptable way to retrieve other user information such as name and email by using userName:req.user.userName in the render function and rendering this information to a p. tag in a jade page by using p #{userName}

Ajax with node.js/jade

I'm searching for a way to use ajax running on node.js, express and jade as template-engine without routing to subpages. I read this: Node, Express, Ajax, and Jade Example
But this doesn't work for me. I don't want to make a route to a partial part of page, so the user could access the partial page. I just want to serve a convertet jade file in a part of the website.
I think about something like this:
$( ".trigger" ).on( "click", function() {
$( ".result" ).load( "ajax/test.jade" );
});
How could I do this without setting a route in node.js so the user could access the subpage without accessing the whole page.
Thank you for your answers.
What if you send the file as a GET parameter:
var jade = require('jade'),
fs = require('fs');
app.get('/ajax', function(req, res) {
fs.readFile(req.query.file, 'utf8', function (err, data) {
if (err) throw err;
var fn = jade.compile(data);
var html = fn({});
res.send(html);
});
});
and send request like
/ajax?file=test.jade
If you do the things like that you will have only one route.
(Still requires a route but) You could set up a route that only provides a valid response if it is an ajax request, and a 4xx if otherwise
app.get('/path', function(req, res) {
if(req.xhr)
{
...
}
});
req.xhr Express docs.
You could place a jade template (or HTML file) in the public folder on your website, assuming you have it set up.
For example, in the app.js:
app.use(express.static(__dirname + '/public'));
Place the template/file in (or any subfolder):
/public/example.html
Then you can use $.get to load the file, like the link you provided:
$.get('/example.html', function(result) {
$('#test').html(result);
});
I have a problem with ajax call
Server side:
router.get('/user/letterlist', function(req, res) {
// ... some operations
res.render('userLetterList', { title: 'test', rows : rows? rows: null, pageCount: pageCount,itemCount: itemCount });
});
Client side index.jade
extends layout
block content
div(id="userLettersList")
button(type="button" class="btn btn-success")
{success}
script.
$(".btn").click(function(e){
e.preventDefault();
$.ajax({
url: "/user/letterlist",
success: function(data){
$("#userLettersList").html(data) ;
}
});
});
client side userLetterList.jade
table(id="UserLetters" class="table table-striped table-bordered")
thead
....
The problem is when push on the button to load data into the div, it will retrieve and show, but the page redirect to nowhere with a blank page, after some m-seconds.

Using the PUT method with Express.js

I'm trying to implement update functionality to an Express.js app, and I'd like to use a PUT request to send the new data, but I keep getting errors using PUT. From everything I've read, it's just a matter of using app.put, but that isn't working. I've got the following in my routes file:
send = function(req, res) {
req.send(res.locals.content);
};
app.put('/api/:company', function(res,req) {
res.send('this is an update');
}, send);
When I use postman to make a PUT request, I get a "cannot PUT /api/petshop" as an error. I don't understand why I can't PUT, or what's going wrong.
You may be lacking the actual update function. You have the put path returning the result back to the client but missing the part when you tell the database to update the data.
If you're using MongoDB and ExpressJS, you could write something like this :
app.put('/api/:company', function (req, res) {
var company = req.company;
company = _.extend(company, req.body);
company.save(function(err) {
if (err) {
return res.send('/company', {
errors: err.errors,
company: company
});
} else {
res.jsonp(company);
}
})
});
This mean stack project may help you as it covers this CRUD functionality which I just used here swapping their articles for your companies. same same.
Your callback function has the arguments in the wrong order.
Change the order of callback to function(req, res).
Don't use function(res, req).
Also if you want to redirect in put or delete (to get adress), you can't use normal res.redirect('/path'), you should use res.redirect(303, '/path') instead. (source)
If not, you'll get Cannot PUT error.
Have you been checking out your headers information?
Because header should be header['content-type'] = 'application/json'; then only you will get the update object in server side (node-express), otherwise if you have content type plain 'text/htm' like that you will get empty req.body in your node app.

Categories

Resources