How to stop other response data with Nodejs - angularjs

I am doing options request data from server by using Nodejs,
but I don't know how to handle response data with delay in same request,
Here's the front code:
HTML(click to request data from server):
<div ng-controller="testCtrl">
<label>
<input type="radio" ng-model="animalSpecies.species" ng-click="selectAnimal()" name="animal" value="Dog"/>Dog
</label>
<label>
<input type="radio" ng-model="animalSpecies.species" ng-click="selectAnimal()" name="animal" value="Cat"/>Cat
</label>
Angular:
function testCtrl($scope, $http) {
var config;
$scope.animalSpecies = {
species: ""
}
$scope.selectAnimal = function () {
config = {
method: "GET",
url: "/getanimal",
params: {
species: $scope.animalSpecies.species
}
}
$http(config).then(
function (res) {
console.log(res.data);
}
)
}
}
Nodejs
app.get("/getanimal", function (req, res) {
var species = req.query.species;
if (species === "Dog") {
setTimeout(function () {
res.send({msg: "species is" + species});
}, 1000)
} else {
res.send({msg: "species is" + species});
}
})
When you click "Dog" option first and quickly click "Cat" option,
the "Cat"'s response data will first come out ,but finally the "Dog"'s
data will response a second later.(I do a setTimeout delay in Nodejs,but maybe
other conditions like querying database callback delay or somehow)
What I want is just:Is there some way to stop server to response data or
I get what I want doing in frontend?

Best way is to disable the control for the user if the first response hasn't come back yet.
Disable the input buttons when the user clicks one of them, and enable them on server response

Related

AngularJS $http PUT request

I am buiding a CRUD apps with AngularJS and Django REST API.
I have created get and post method successfully but not getting how to put request. i tried stackoverflow lots of problem and youtube but i couldnt sort it out.
my current controller is:
app.controller('crudCtrl', function($scope, $http) {
$http.get("http://127.0.0.1:8000/api/v1/contact/?format=json")
.then(function(response) {
$scope.contacts = response.data; //this is get method that displayed all the list of contact
});
$scope.formModel = {}; // this is same input.js, it is POST method to to send data to database
$scope.onSubmit = function () {
console.log("hey, i am submitting");
console.log($scope.formModel);
$http.post('http://127.0.0.1:8000/api/v1/contact/', $scope.formModel).
success(function (data) {
console.log(":)");
}).error(function (data) {
console.log(":(");
});
};
$scope.selectUser = function (contact) {
console.log(contact); // it will select the data exactly where you click
$scope.clickedUser = contact;
};
$scope.updateUser = function (argument) { // it will get the form editable exactly which contact you clicked
};
});
and my edit view is, when i click on edit buttion, the form will be appear:
<form>
<input type="text" ng-model="clickedUser.userid">
<input type="text" ng-model="clickedUser.name">
<input type="text" ng-model="clickedUser.email">
<input type="text" ng-model="clickedUser.phone">
<button type="submit" ng-click="updateUser()" data-dismiss="modal">Submit</button>
</form>
Point to be noted, the edit form working nice on client side but it doesnt send the data to backend/API/Database.
can anyone tell me how can i do $http.put request? i tried w3school, youtube, and stackoverflow problem.
i got huge solution but i couldnt solve it.
this is my api endpoint for anything: http://127.0.0.1:8000/api/v1/contact/ so if i want to update particular field, i have to go through this url: http://127.0.0.1:8000/api/v1/contact/1 in the end of the url is id
I hope it is clear to you
You can try this as well
$http({method: "PUT", url: URL}).
then(
function(response) {
}, function(response) {
});
Can you just use angular put?
See: https://docs.angularjs.org/api/ng/service/$http#put
var clientData = {
text: "Put this somewhere"
};
$http.put( url, clientData ).then( function( serverResponse ) {
console.log(serverResponse);
},( error )=>{
console.log(serverError);
});

Error In $http PUT

I'm building a simple auction site. I showed my products in the page. Now i wanna make a new offer. in my controller i use ng-dialog to open a pop-up form and i pass inside the auction that i need. like this:
$scope.clickToOpen4 = function (followingauction) {
console.log(followingauction.allbids[followingauction.allbids.length -1].bid);
var newScope = $scope.$new();
newScope.auction = followingauction;
ngDialog.open({template: '../views/partials/offer.html',
className: 'ngdialog-theme-default',
scope: newScope
});
};
In my template offer.html i have a simple form:
<form name="Offer" ng-controller="FollowingAuctionsController">
Your Offer:<br>
<input type="number" placeholder="Your Offer" ng-model="newOffer" name="new offer" required> €<br>
<input class="btn" type="submit" ng-click="submitNewOffer(auction._id, auction.allbids[auction.allbids.length -1].bid)" value="OK"><br>
And in the submitNewOffer i pass, the id of the auction and the highest offer.
And this is the submitnewOffer():
$scope.submitNewOffer = function (id, bid) {
console.log(id);
console.log(bid);
var newBid = $scope.newOffer;
if (newBid>bid) {
console.log(newBid);
console.log('/api/followingauctions/newoffer/' + id);
$http.put('/api/followingauctions/newoffer/' + id, newBid)
.then(function () {
alert('Offert Done!');
getFollowingAuctions();
});
}
else {
alert('The offer must be higher!');
$scope.newOffer = '';
}
};
Like you see i do the console.log to see if the data that i passed into the template are ok. They are!
Than if the new bid is less than the highest bid that i passed, i send that alert, else i put the new offer.
All works fine and all the console.log are fine. But when i submit the newBid (that is higher than the old bid) it send me this error:
angular.js:12578 PUT http://localhost:3001/api/followingauctions/newoffer/58dbd190b8042b080d1418bf 400 (Bad Request)
angular.js:14516 Possibly unhandled rejection: {"data":"Unexpected token 8400SyntaxError: Unexpected token 8\n at parse (/Users/m.pagano/WebstormProjects/Challenge_2/Project2/sampsite/node_modules/body-parser/lib/types/json.js:83:15)\n at /Users/m.pagano/WebstormProjects/Challenge_2/Project2/sampsite/node_modules/body-parser/lib/read.js:116:18\n at invokeCallback (/Users/m.pagano/WebstormProjects/Challenge_2/Project2/sampsite/node_modules/raw-body/index.js:262:16)\n at done (/Users/m.pagano/WebstormProjects/Challenge_2/Project2/sampsite/node_modules/raw-body/index.js:251:7)\n at IncomingMessage.onEnd (/Users/m.pagano/WebstormProjects/Challenge_2/Project2/sampsite/node_modules/raw-body/index.js:307:7)\n at emitNone (events.js:86:13)\n at IncomingMessage.emit (events.js:185:7)\n at endReadableNT (_stream_readable.js:974:12)\n at _combinedTickCallback (internal/process/next_tick.js:74:11)\n at process._tickCallback (internal/process/next_tick.js:98:9)","status":400,"config":{"method":"PUT","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"/api/followingauctions/newoffer/58dbd190b8042b080d1418bf","data":800,"headers":{"Accept":"application/json, text/plain, /","Content-Type":"application/json;charset=utf-8"}},"statusText":"Bad Request"}
You are using the method incorrectly.
The right signature of $http.put method is put(url, data, [config]);
So, your code could look like this:
$http.put('/api/followingauctions/newoffer/' + id, {newBid: newBid})
.then(function () {
// success
});
and you can access newBid from POST at the backend
OR
$http.put('/api/followingauctions/newoffer/' + id, {}, {params: {newBid: newBid}})
.then(function () {
// success
});
in which case, newBid can be obtained from GET at the backend
When doing a PUT request with $http, you have to specify the params:
$http.put('/api/followingauctions/newoffer/' + id, {}, params: {'newBid': newBid})
.then(function () {
alert('Offert Done!');
getFollowingAuctions();
});

Use data from angular to make external api call in node express

I am trying to use data that the user inputs to make an api call to an external API using node. I have successfully made calls from the server, and returned them to angular. But I need to send the server a variable from angular, have it make a call, and return the response to my view. I am new to node so I am sorry if this has already been answered somewhere. I looked around and found nothing.
My html
<md-input-container class="md-block" flex-gt-sm>
<label>Player 1</label>
<input ng-model="player1.username">
</md-input-container>
<md-button ng-click="comparePlayers(player1, player2)">COMPARE!</md-button>
My controller function
$scope.comparePlayers = function(player1) {
Nerd.getPlayer(player1)
}
My 'Nerd' Service
smiteStats.factory('Nerd', ['$http', function($http) {
return {
getPlayer: function(playerName) {
$http.post('/api/getPlayer', playerName).success(function(data) {
console.log("sent to server"); //does not run
})
}
}]);
My Express Route
app.post('/api/getPlayer', GetPlayer.apiGetPlayer);
My node module that makes the api call
module.exports = {
apiGetPlayer: function(error, res, player) {
console.log(player); //this returns "[Function: next_layer] in my cmd
}
}
To send Parameters with $http in POST:
$http({
url: host + '/api/getPlayer',
method: "POST",
data: { 'fruit1' : "Apple"}
})
.then(function(response) {
// success
},
function(response) { // optional
// failed
});
To get POST parameters, you will need the ExpressJS body-parser package. This will allow you to grab information from the POST.
Read more

Can't set headers after they are sent - Posting new Users through NodeJs

I'm trying to build an application using Google Maps API, NodeJs, Express, MongoDB, Mongoose and AngularJS and I'm facing a problem that I wasn't able to solve looking at other related SO Q/A.
Basically, I'm trying to post into my db users identified by an username and [latitude, longitude] who submit a certain form that I have in my view.
When I try to post users directly from applications like Postman everything goes ok, I'm able to see new users in my db.
When, instead, I try to post users directly when they submit, I get the following error in my Console:
/node_modules/mongodb-core/lib/topologies/server.js:766
catch(err) { process.nextTick(function() { throw err}); }
^
Error: Can't set headers after they are sent.
and the following log in my Google Chrome Console:
angular.js:10695 GET http://localhost:3000/users net::ERR_CONNECTION_REFUSED
Here is my View:
<form name="addForm" novalidate>
<div class="form-group">
<label for="username">Username
<span class="badge">All fields required</span>
</label>
<input type="text" class="form-control" id="username"
placeholder="OldandGold" ng-model="formData.username" required>
</div>
<div class="form-group">
<label for="latitude">Latitude</label>
<input type="text" class="form-control" id="latitude"
value="39.500" ng-model="formData.latitude" readonly>
</div>
<div class="form-group">
<label for="longitude">Longitude</label>
<input type="text" class="form-control" id="longitude"
value="-98.350" ng-model="formData.longitude" readonly>
</div>
<button type="submit" class="btn btn-danger btn-block"
ng-click="createUser()" ng-disabled="addForm.$invalid">Submit</button>
</form>
Here is my Schema:
// Pulls Mongoose dependency for creating schemas
var mongoose = require('mongoose');
var GeoJSON = require('geojson');
var Schema = mongoose.Schema;
var LocationSchema = new Schema({
name: {type: String, required: true},
location: {
type: {type : String, required: true},
coordinates : [Schema.Types.Mixed]
},
created_at: {type: Date, default: Date.now},
updated_at: {type: Date, default: Date.now}
});
// Sets the created_at parameter equal to the current time
LocationSchema.pre('save', function(next){
now = new Date();
this.updated_at = now;
if(!this.created_at) {
this.created_at = now
}
next();
});
// Indexes this schema in 2dsphere format (critical for running proximity searches)
LocationSchema.index({location: '2dsphere'});
module.exports = mongoose.model('mean-locations', LocationSchema);
Here is my Controller's createUser function:
$scope.createUser = function($rootScope, $on) {
// Grabs all of the text box fields
var userData = {
name: $scope.formData.username,
location: {
type: "Point",
coordinates: [$scope.formData.latitude,
$scope.formData.longitude]
}
};
console.log(JSON.stringify(userData));
// Saves the user data to the db
$http.post('/users', userData)
.success(function(data) {
// Once complete, clear the form (except location)
$scope.formData.username = "";
})
.error(function(data) {
console.log('Error: ' + data);
});
};
And, finally, here are my routes:
app.get('/users', function(req, res) {
// Uses Mongoose schema to run the search (empty conditions)
var query = User.find({});
query.exec(function(err, users) {
if (err)
res.send(err);
// If no errors are found, it responds with a JSON of all users
res.json(users);
});
});
// POST Routes
// --------------------------------------------------------
// Provides method for saving new users in the db
app.post('/users', function(req, res) {
// Creates a new User based on the Mongoose schema and the post body
var newuser = new User(req.body);
// New User is saved in the db.
newuser.save(function(err) {
if (err)
res.send(err);
// If no errors are found, it responds with a JSON of the new user
res.json(req.body);
});
});
Using my Stringify Log I'm able to see a proper json:
{"name":"MyPoint","location":{"type":"Point","coordinates":["50.064","16.260"]}}
I'm pretty new to NodeJs and I don't understand why this keeps happening.
What does cause this? How Can I solve this?
Thanks In Advance.
The problem is here, you have to stop execution if there is an error. (Note the return). For example if there's an error, in your code will send (res.send) the error and continues executing res.json() what it will end with the error you mentioned, because you have already set the header and send the response.
newuser.save(function(err) {
if (err)
return res.send(err);
// If no errors are found, it responds with a JSON of the new user
res.json(req.body);
});
The "Error: Can't set headers after they are sent." error usually indicates that you are sending multiple responses (using express).
For instance this code will (try) to send two responses in case of error
app.get('/users', function(req, res) {
// Uses Mongoose schema to run the search (empty conditions)
var query = User.find({});
query.exec(function(err, users) {
if (err)
res.send(err); // first response
// If no errors are found, it responds with a JSON of all users
res.json(users); // second response
});
});
To Fix this, ensure to exit after response has been send:
app.get('/users', function(req, res) {
// Uses Mongoose schema to run the search (empty conditions)
var query = User.find({});
query.exec(function(err, users) {
if (err) {
res.send(err);
return; // return here!
}
// If no errors are found, it responds with a JSON of all users
res.json(users);
});
});

MEAN.JS Contact Form

Trying to create a contact form and feedback form for my website. Here is my route and controller I'm using however I need to understand what's going on with my routes and how to capture the input fields from the form implement this inside MEAN.JS:
route.js:
app.route('/mail').get(mail.createmail);
app/controller.js:
exports.createmail = function(req, res) {
var mailOpts, smtpTrans;
// create reusable transporter object using SMTP transport
var transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: 'administrator#radleaf.com',
pass: '34Girls34*goo'
}
});
// NB! No need to recreate the transporter object. You can use
// the same transporter object for all e-mails
// setup e-mail data with unicode symbols
var mailOptions = {
from: 'Fred Foo ✔ <foo#blurdybloop.com>', // sender address
to: 'ty#radleaf.com', // list of receivers
subject: 'Hello ✔', // Subject line
text: 'Hello world ✔', // plaintext body
html: '<b>Hello world ✔</b>' // html body
};
// send mail with defined transport object
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
console.log(error);
} else {
console.log('Message sent: ' + info.response);
}
});
};
Not sure how this work with the HTML with the view:
<form action="mail">...</form>
If I understand the question correctly, you're asking how you can gather data which is input into a form, send that data to expressJS, and then use that data to send an outbound email.
If so, then here is your flow:
Step 1: Create a form in a view and map it to an AngularJS controller
<form name="contactForm" data-ng-submit="sendMail()">
Name: <input type="text" data-ng-model="contact_name">
Message: <input type="text" data-ng-model="contact_msg">
<button type="submit">
</form>
Step 2: In your AngularJS controller, use a $http request to send your data to your Express Route
$scope.sendMail = function() {
// Simple POST request example (passing data) :
$http.post('/mail', {name: contact_name, msg: contact_msg}).
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
}
Step 3: Use your ExpressJS Route as an API to call your ExpressJS Controller.
(It looks like you've got this bit covered)
app.route('/mail').get(mail.createmail);
Step 4: Receive and do something with the data passed through the $http POST
exports.createmail = function(req, res) {
var data = req.body;
Now you can use the data, like this
var mailOptions = {
from: data.name, // sender name
text: data.msg, // plaintext body
};
MeanJS 0.4.0 also has a working example of NodeMailer which might help: https://github.com/meanjs/mean/tree/0.4.0
With angularJS, you can remove the action attribute, and just use angularJS ngSubmit directive, and call a function in your controller which would now visit the endpoint with $http.get.

Resources