MongoDB is posting no data with Mongoose - angularjs

I am making an app with the MEAN stack and I am having trouble POSTing data to my database. When I push the submit button, the form data is being cleared, like it is supposed to when the POST is sucessful, but when I go to the database, there is a new document with nothing in it but and id and __v.
There aren't any errors that are being thrown because there is data being posted to the DB, but not the correct data (Look at the mongodb document at the bottom of the page)
The form where the data is being posted to is this:
<input name="userName" type="String" class="form-control" id="userName" ng-model="formData.userName" placeholder="Your Name">
<input name="game" type="String" class="form-control" id="game" ng-model="formData.game" placeholder="The game?">
<input name="userPoint" type="Number" class="form-control" id="userPoint" ng-model="formData.userPoint" placeholder="Points?">
<button type="submit" class="btn btn-default" ng-click="createScore()">Submit</button>
This is createScore():
$http.post('/api/scores', $scope.formData)
.success(function(data) {
$scope.formData = {};
$scope.scores = data;
console.log(data);
})
.error(function(data) {
console.log('Error: ' + data);
});
This is the Mongoose model for the database:
var Score = mongoose.model("Score", {
userName: String,
game: String,
userPoint: Number
}, "score");
And this is the route for my express's "app.post()":
app.post("/api/scores", function(req, res){
Score.create({
userName:req.body.userName,
game:req.body.game,
userPoint:req.body.userPoint
}, function(err, score) {
if (err)
res.send(err);
Score.find(function(err, score) {
if (err)
res.send(err)
res.json(score);
});
});
});
When the data is POSTed, the mongodb file document looks like this:
{
"_id": {
"$oid": "54cbf3d1fbaaf10300000001"
},
"__v": 0
}
I was thinking that maybe the names were wrong (ex. userPoints and userPoint), but I made sue that they were all the same. Also, I'm new to this, so if you have any tutorials that might help concrete a topic, please feel free to share.
EDIT 1:
I did a console.log() on the node.js part where it says req.body.userName, req.body.game, etc. And in the logs, they all came out as undefined. I have been looking for a solution online, but I can't seem to find a solution. I have tried making the types in the HTML file "String" instead of "text", but that did not seem to work. Any ideas?

Ok, so I fixed my problem.
I was trying to POST as a form-data instead of a x-www-form-urlencoded.
In my core.js, I put this in the createScore method:
$http({
method : 'POST',
url : '/api/scores',
data : $.param($scope.formData),
headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function(response){
$scope.formData = {};
$scope.scores = response;
console.log(response);
});
I hope this helps someone!

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);
});

How do I get my database to not append the status when I do an api call?

So I'm trying to create a simple blog app using the MEAN stack. I am able to successfully write to my local mongo DB but when I make a call to my DB, it appends additional information to my query which makes it hard to ng-repeat. Here's what the response look like:
[{"_id":"135","title":"aaaaaa","body":"aaaaaa","__v":0,"posted":"2017-08-05T08:46:27.159Z"},
{"_id":"136","title":"bbbbb","body":"bbbbb","__v":0,"posted":"2017-08-05T08:46:40.232Z"}]
200
function (d){b||(b=vd(a));return d?(d=b[Q(d)],void 0===d&&(d=null),d):b}
{"method":"GET","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"/api/blogpost","headers":{"Accept":"application/json, text/plain, */*"}}
OK
I just want the first two elements with "aaaa" and "bbbb" in the object so I can use ng-repeat to get the title, body, etc. This is how I'm displaying the information on my index.html:
<input ng-model="post.title" class="form-control" placeholder="title">
<textarea ng-model="post.body" class="form-control" placeholder="body"></textarea>
<button ng-click="createPost(post)" class="btn btn-primary btn-block">Post</button>
<div ng-repeat="post in posts">
{{post}}
</div>
Here's how my Angular get code looks:
function getAllPosts() {
$http({
method: 'get',
url: '/api/blogpost'
}).then( function (posts){
$scope.posts = posts;
}, function (error){
console.error("Inside app.js._getAllPosts().error");
});
}
And here is my backend:
app.get("/api/blogpost", getAllPosts);
function getAllPosts(req, res) {
var post = req.body;
PostModel
.find()
.then(
function (post) {
res.json(post);
},
function (error) {
res.sendStatus(400);
}
);
}
I can post the rest of my code if needed.
I think you just need to reference the data property on your success callback:
}).then(function(response) {
$scope.posts = response.data;
Use the key name to access the specific object.
<div ng-repeat="post in posts">
{{post.title}} {{post.body}}
</div>

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);
});
});

Model array values are not being submitted by $http service

I defined an array in controller to create a array model. i.e. $scope.campaignPublish[] and I am using in my view template like
<textarea rows="" cols="" name="description" ng-model="campaignPublish['description']"> </textarea>
<input type="text" name="title" ng-model="campaignPublish['title']">
When I submit the form I'm getting all of the form values in this array i.e. $scope.campaignPublish[] but when I'm using $http.post, the data is not being submitted to server. My ajax call is
console.log($scope.campaignPublish); // Getting all form data here
$http.post('url', {'id': campaignId, 'data': $scope.campaignPublish}).then(function (response) {
//$http.post is not submitting the form data on server
});
I read some articles and got to know that it is happening because of http headers. I've already tried each and every solution posted on SO but no one exactly worked. Can anybody tell me where I am doing wrong ?
$http({
method: 'POST',
url: url,
headers: {
'Content-Type': 'text/plain'
},
data: $scope.campaignPublish
}).success(function (reply) {
console.log('sucess');
}).error(function (reply) {
console.log('error');
});

Store File Locally via Mongoose Crate with MEAN app

I'm having a bit of trouble setting up Mongoose Crate with my REST API using the MEAN stack. I'm pretty new to the whole thing so take it easy on me. I want to be able to upload a file to a local directory and then display that image within the controller. My route is setup as follows:
router.post('/posts', auth, function(req, res, next) {
var post = new Post(req.body);
post.author = req.payload.username;
// Mongoose Crate attach method
post.attach('image', req.files.image, function(err, post) {
if(err){ return next(err); }
post.save(function(err, post) {
if(err){ return next(err); }
res.json(post);
});
});
});
This is my Post model:
var mongoose = require('mongoose');
var crate = require('mongoose-crate');
var LocalFS = require('mongoose-crate-localfs');
var PostSchema = new mongoose.Schema({
title: String,
author: String
});
PostSchema.plugin(crate, {
storage: new LocalFS({
directory: './public/uploads'
}),
fields: {
image: {}
}
});
mongoose.model('Post', PostSchema);
And my controller:
app.controller('FeedCtrl', [
'$scope',
'posts',
function($scope, posts) {
$scope.posts = posts.posts;
$scope.addPost = function() {
posts.create({
title: $scope.title,
author: $scope.author,
image: $scope.image
});
$scope.title = '';
}
}
]);
And on the front end:
<form ng-submit="addPost()" method="post" enctype="multipart/form-data">
<div>
<input type="file" name="image" id="image">
</div>
<div class="message">
<input type="text" placeholder="Title" ng-model="title">
</div>
<button type="submit"></button>
</form>
<div>
<h3>{{post.title}}</h3>
<img src="{{post.image}}"/>
<span>posted by <a>{{post.author}}</a></span>
</div>
I read that by using Express you can get an uploaded file by just the input name and using req.files but I can’t seem to get that too work within the scope. If I’m reading that Mongoose Crate plugin correctly, it should save it to a directory of your choice (using the mongoose-crate-localfs plugin), by adding it to the “Post” model, and send back an array of the file meta data. I'm not able to retrieve any data after the post.
I feel like that scene in Seinfeld when they’re trying to write the script: https://www.youtube.com/watch?v=q9eDwHznMas. “Now we need something here…”. I just don’t know what it is. If someone can please take a look and please get me out of this funk that would be amazing. Thank you so much!
Express does not come with a multipart parser out of the box, req.files will be undefined if you are not using a multipart parsing middleware. A good multipart middleware to check out is multer, very easy to use. Also if you are planning making this an XHR request you will need to use the FormData api, and explicitly tell angular not to process the data. Im sure there are many good third party solutions but here is an article worth reading.

Resources