Saving node.js post data to show all records that have been added since the web application was started - javascript

I'm working on a web application using node.js that has a form containing basic information about a person. I need to have all records that have been added since the web application was started display on the submit page.
I believe that I need to create an array to store this information but this is where my confusion starts. I'm not sure where to create the array to add information to. I suspect it should be in app.js where I call app.post('/add', routes.add);
I think it should maybe something like this going from an example I found here How do I add a new complex entry to a javascript array?:
// Routes
app.get('/', routes.index);
app.post('/add', routes.add);
var people = [{name, country, date, email, phone}];
people.push({name, country, date, email phone});
However the array looks like it will only hold enough information for 1 person.
Please let me know if my question is not clear enough and I will try to clarify
Thanks in advance!
Edit: I believe that when I am calling routes.add this code is executed from my index.js file
exports.add = function(req, res){
res.render('add', { title: 'Person added',
name: req.body.name,
country: req.body.country,
date: req.body.birthday,
email: req.body.email,
phone: req.body.phone});
};
and in my add.jade file:
h1 Info Added
p Name: #{name}
p Country: #{country}
p Date: #{date}
p Email: #{email}
p Phone: #{phone}

There are a few things to maybe get you started.
Database
I suggest you move the database to another file, that way you may replace it with a 'real' database later. Ie. do something like this:
create a lib directory in app root,
create a db.js in that directory,
put this code in the db.js:
var database = [],
counter = 0;
// add method adds a new object to db.
exports.add = function(person) {
person.id = counter;
counter = counter + 1;
database.push(person);
return id; // we return id, so that we can use it as a reference to this object.
}
// get method retreives the object by id.
exports.get = function(id) {
return database[id]; // this will return undefined if there is no such id
};
exports.list = function(){
return database;
}
Now you have a database.
Controllers
You use the db in other files like this:
var people = require('lib/db');
// or if you're in a routes directory,require('../lib/db') or appropriate path
people.add({name: 'Sarah'}); // returns 0
people.add({name: 'Zlatko'}); // returns 1
people.get(1); // returns {name: 'Zlatko'}
Now in your routes/index.js you can include your database and have this to save or retreive an user or all users. Somehing similar to your exports.add:
var id = people.add({name: req.body.name, email: req.body.email});
res.render('add', people.get(id));
You can also create a 'people' view and just pass it {people: people.list()} object as parameters array.
I didn't include any validation, checking, anything ,to make the example more clear. This db can hold more then one person, and it's enough to get you started. And I think it is clear in what it does.
I hope this helps.

Related

Question about Model in MVC architecture in web app using NodeJs and MySQL

I am new to NodeJs and I am trying to create a web application using express framework and MySql. I get that in MVC architecture the views are for example the *.ejs files. The controllers are supposed to have the logic and the models should focus on the database.
But still I am not quite sure what is supposed to be inside the model. I have the following code in my controller (probably wrong, not following mvc design):
const mysql = require('mysql');
const db = mysql.createConnection(config);
db.query(query, (err, result) => {
if (err) {
return res.redirect('/');
}
res.render('index.ejs', {
users: result
});
});
Now from what I've read the controller should ask the model to execute the query to the database, get the results and render the view (index.ejs').
My question is this: What should be inside the model.js file? Can I make something like this?
controller.js
const db = require('./models/model.js');
db.connect();
const results = db.query(query);
if(results != null) {
res.render('index.ejs'){
users: result
});
}
model.js will make a query to mysql handle any errors and return the result.
From what I've read I have two options. Option1: pass callback function to model and let the model render the view (I think that's wrong, model should not communicate with view, or not?) Option2: possible use of async/await and wait for model to return the results but I am not sure if this is possible or how.
The model is the programmatic representation of the data stored in the database. Say I have an employees table with the following schema:
name: string
age: number
company: company_foreign_key
And another table called companies
name: string
address: string
I therefore have two models: Company and Employee.
The model's purpose is to load database data and provide a convenient programmatic interface to access and act upon this data
So, my controller might look like this:
var db = require('mongo');
var employeeName = "bob";
db.connect(function(err, connection){
const Employee = require('./models/Employee.js'); // get model class
let employeeModel = new Employee(connection); // instantiate object of model class
employee.getByName(employeeName, function(err, result){ // convenience method getByName
employee.getEmployeeCompany(result, function(err, companyResult){ // convenience method getEmployeeCompany
if(companyResultl) { // Controller now uses the results from model and passes those results to a view
res.render('index.ejs')
company: companyResult
});
})
})
}
})
Basically, the model provides a convenient interface to the raw data in the database. The model executes the queries underneath, and provides convenient methods as a public interface for the controller to access. E.g., the employee model, given an employee object, can find the employee's company by executing that query.
The above is just an example and, given more thought, a better interface could be thought up. In fact, Mongoose provides a great example of how to set up model interfaces. If you look at how Mongoose works, you can use the same principles and apply them to your custom model implementation.

Mongoose how to see which mongodb query is being generated nothing returned from database

I'm currently using mongodb with mongoose.
When I connect to the database via the terminal and run the command:
db.locphoto.find({})
It successfully returns the list of items that I'm looking for.
Alternatively, on my application I do the following and unfortunately it constantly returns []. I was hoping someone could show me the way to see which mongodb query is generated so that I'm able to check if it is correctly generating db.locphoto.find({}).
My controller code is as follows:
var LocPhoto = require('../models/locPhoto');
module.exports.getGalleryPictures = function(req, res) {
LocPhoto.find({}, function(err, results) {
res.json(results);
});
}
And my model code is as follows:
var mongoose = require('mongoose');
var locPhotoSchema = mongoose.Schema({
challengeId: String,
image: String,
main: Number,
});
module.exports = mongoose.model('LocPhoto', locPhotoSchema);
I'd really appreciate if someone knows how to see the command that is being generated so that I can check this better in the future, since I've had this issue a few times already, it's usually to do with capital letters etc.
You're not properly creating the schema , you have to use new keyword
var locPhotoSchema = new mongoose.Schema({
challengeId: String,
image: String,
main: Number,
});

Create a dynamic meteor collection using a variable

I am trying to create a dynamic meteor collection using a variable so a new meteor collection will be created everytime an form is submitted and an event is executed. See code below for what I am looking for though is does not work.
(Keep in mind I am still in the early production stages so I have not set up specific server or client side for debugging purposes. Also, disregard any grammatical or structure errors as i just typed this. just how to make it work)
Intended result:
Suppose user 1 meteor id is x533hf4j3i
Suppose user 2 meteor id is jf83jfu39d
OUTCOME: x533hf4j3ijf83jfu39d = new Mongo.Collection('x533hf4j3ijf83jfu39dmessages')
this sample code that DOES NOT WORK
Template.createChat.events({
'submit form': function(event){
event.preventDefault();
var messageRecipientVar = event.target.messageRecipient.value;
var currentUserId = Meteor.userId();
var recipientUserId = Meteor.users.findOne(messageRecipientVar)._id;
var chatCollectionNameVar = {$concat: [currentUserId, recipientUserId]}
var chatCollectionName = {$concat: [currentUserId, recipientUserId, "messages"]}
chatCollectionNameVar = new Mongo.Collection('chatCollectionName');
}
});
Don't do this. Asking how to create dynamic collections comes up periodically with new meteor developers, but it's never the right approach. #david-wheldon has a great description of why not to do this at the bottom of this page.
Just use one collection Messages, containing documents something like this:
{ _id: xxxxxx,
sender: 'x533hf4j3i',
recipient: 'jf83jfu39d',
message: 'Hi there!',
...
timestamp, etc
...
}
Then it depends on your app if a user can view messages they did not send/receive, and if you need filtering on this you would do it server side in a publish function.
Either way, on the Client if you just want the messages between two users you would query like this:
chatMessages = Messages.find(
{$or: [{ sender: 'x533hf4j3i', recipient: 'jf83jfu39d'},
{ sender: 'jf83jfu39d', recipient: 'x533hf4j3i'}
]}).fetch()

Mongoose: Adding an element to array

I'm using Drywall to create a website.
I'm trying to add a dashboard element to the accounts section of the admin site. The dashboard element is to store an array of dashboards (strings) that the user has access to.
I've managed to successfully add the "dashboards" into the schema and store data in it.
Here's the problem:
I need to be able to add elements to the array. The way the code stands currently replaces the contents of dashboards in the database.
I know I can use $addToSet, but I'm not sure how I'd do that since the fieldsToSet variable is sent to the findByIdAndUpdate() method as a single object.
Here's the snippet of my code:
workflow.on('patchAccount', function() {
var fieldsToSet = {
name: {
first: req.body.first,
middle: req.body.middle,
last: req.body.last,
full: req.body.first +' '+ req.body.last
},
company: req.body.company,
phone: req.body.phone,
zip: req.body.zip,
search: [
req.body.dashboards,
req.body.first,
req.body.middle,
req.body.last,
req.body.company,
req.body.phone,
req.body.zip,
]
};
req.app.db.models.Account.findByIdAndUpdate(req.params.id, fieldsToSet, function(err, account) {
if (err) {
return workflow.emit('exception', err);
}
workflow.outcome.account = account;
return workflow.emit('response');
});
});
Here's a link to the original file: (lines 184-203)
Thanks!
fieldsToSet is a bad name (at least misleading in this case), the parameter is actually update which can take $actions like $addToSet
I don't think you want to set (only) the search field with dashboards. I'm guessing that field is used to index users for a search. So you'll probably wind up doing something like this:
fieldsToSet = {
....all the regular stuff,
$addToSet: {dashboard: req.body.dashboardToAdd}
//I'm not sure that you can add multiple values at once
}
Since this is setting all of the values each time I'm not sure you actually will want to add single dashboard items. Instead you might want to get the full set of dashboards the user has and set the whole array again anyway (what if they removed one?)
fieldsToSet = {
....all the regular stuff,
dashboards: req.body.dashboards
//In this case you'd want to make sure dashboards is an appropriate array
}

How do I post an HTML class into a mongoDB collection using express/mongoose and client-side JS?

First off my programming knowledge is entirely on the front-end, but I'm experimenting with node, express, mongoose, and mongodb. I'm using someone else's template to try and build an app the right way, but I'm lost when connecting the dots. I have the following jade:
form(method='post', action="/post/comment/" + post.id)
textarea(name='text')
input(type='submit', value='Save')
Combined with this from the routes/posts.js file
app.post("/post/comment/:id", loggedIn, function (req, res, next) {
var id = req.param('id');
var text = req.param('text');
var author = req.session.user;
Comment.create({
post: id
, text: text
, author: author
}, function (err, comment) {
if (err) return next(err);
res.redirect("/post/" + id);
});
});
and this is models/comment.js :
var mongoose = require('mongoose');
var ObjectId = mongoose.Schema.Types.ObjectId;
var createdDate = require('../plugins/createdDate');
var schema = mongoose.Schema({
text: { type: String, trim: true, validate: validateText }
, post: { type: ObjectId, index: true }
, author: String
})
function validateText (str) {
return str.length < 250;
}
schema.plugin(createdDate);
module.exports = mongoose.model('Comment', schema);
Now this works fine, for submitting a comment and saving it in the DB. Problem is, is that I don't want to save a comment, but HTML after a function has manipulated it. So I tried:
var everything = $('.whatever').html();
$.post("/post/comment/:id", everything,
function(){
console.log('html saved!')
}
)
But I got a POST http://localhost:3000/post/comment/:id 500 (Internal Server Error) Now I'm aware that I probably don't have the id variable so I tried pasting in the number that is in the url, and that seemed to go through without error, but than didn't show up in the DB. I'm aware that this may not be a specific question, and that I may be going about this entirely wrong but any general direction would be much appreciated. Thanks.
You seem to have a number of problems here. Try taking a look at the following:
Your router is set to receive posts to "/post/comment/:id", but your post in the last code block is posting to "/post/comments/:id", where comments is plural. This will likely result in a 404. (Check the networks tab of your browser javascript console. It may be silently failing without you realizing it).
Your 500 error is likely coming from the fact that you directly posted ":id", instead of an actual identifier. Many node apps will have an app.param() block set up to validate these parameters, and your friend's template is likely breaking when it doesn't get a number it expects.
The data that you post must match the schema of the model you're saving it to. Any keys that aren't named in the schema will be stripped prior to saving, and in your case, if no keys match, it will just be a default comment instance, and won't save at all.
Hope that helps!

Categories

Resources