I am unable to load data(from MongoDB) to the handlebar template engine.when I console.log ArticleModel.find() its show data.But can't render data in the template engine.
Thanks in advance.
App.js
const handlebars = require("express-handlebars"); //Loads the handlebars module
let ArticleModel = require("./model/article");
var mongoose = require("mongoose");
var mongoDB = "mongodb://127.0.0.1/article";
mongoose.connect(mongoDB, { useNewUrlParser: true, useUnifiedTopology: true });
var db = mongoose.connection;
db.on("error", console.error.bind(console, "MongoDB connection error:"));
//Sets our app to use the handlebars engine
app.set("view engine", "hbs");
//Sets handlebars configurations (we will go through them later on)
app.engine(
"hbs",
handlebars({
layoutsDir: __dirname + "/views/layouts",
extname: "hbs",
partialsDir: __dirname + "/views/partials/"
})
);
app.use(express.static("public"));
app.get("/", function (req, res) {
ArticleModel.find({}, function (err, result) {
if (err) {
console.log(err);
} else {
res.render("main", { layout: "index", data: result });
}
});
});
//stating server
app.listen(PORT, () => {
console.log(`Server started at port ${PORT}`);
});
main.hbs
<h1>{{name}}</h1>
<ul>
{{#each data}}
<li>{{title}}</li>
{{/each}}
</ul>
Related
I have this todo_list app built using:
Node.js
Express.js
EJS
MySQL
Choosing a database by following instructions from this Express website:
https://expressjs.com/en/guide/database-integration.html#mysql
https://expressjs.com/en/guide/database-integration.html#postgresql
I managed to make MySQL work with my todo_list app. But I'm having trouble refactoring the same CRUD (create) code for PostgreSQL use. Below is the working MySQL CRUD code and the unfinished PostgreSQL CRUD code for comparison. What am I doing wrong?
MySQL CRUD (create) code = works!
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static("public"));
// _____________________________________________________________________________
// Add new list item - MySQL
let mysql = require('mysql');
let connection = mysql.createConnection({
host: 'localhost',
user: 'dbuser1',
password: '12345',
database: 'testdb1',
});
app.post("/", function(req, res) {
const itemName = req.body.newItem;
let data = { name: itemName };
let sql = "INSERT INTO `todo_list` SET ?";
let query = connection.query(sql, data, function(err, results) {
if (err) throw err;
res.redirect('/');
});
});
PostgreSQL CRUD (create) code = doesn't work!
// .............................................................................
// Add new list item - PostgreSQL
// Loading and initializing the library without Initialization Options.
const pgp = require('pg-promise')();
const connection = {
user : 'pig1',
password : '12345',
host : 'localhost',
port : '5432',
database : 'todo_list'
};
// Database instance
const db = pgp(connection);
app.post("/", function(req, res) {
const itemName = req.body.newItem;
let data = { name: itemName };
let sql = "INSERT INTO todo_list SET ?";
db.any(sql, data)
.then(results => {
console.log(`Inserted data into database!`);
console.log('DATA:', results);
res.redirect('/');
})
.catch(error => {
console.log('ERROR:', error);
})
.finally(db.$pool.end);
});
Thanks for the pointers! #vitaly-t #rabhi-salim
I managed to make the CRUD (create) code work with PostgreSQL now.
app.post("/", function(req, res) {
const itemName = req.body.newItem;
let data = { name: itemName };
async function askStackOverflow() {
try {
await db.none('INSERT INTO todo_list(${this:name}) VALUES (${this:csv})', data);
// --- SUCCESS ---
console.log(``);
console.log(`Inserted data into database!`);
console.log(`DATA:`, insertedItem);
res.redirect('/');
} catch(error) {
// --- ERROR ---
console.log('ERROR:', error);
}
}
(async () => {
await askStackOverflow();
})();
});
Extra reading material:
Promises, Callback Hell, Async Await (ES7)
https://www.digitalocean.com/community/tutorials/javascript-promises-for-dummies
https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example#insert-with-result
https://www.npmjs.com/package/pg-promise#named-parameters
I am basically trying to make a small application which allows an admin user to enter a name, price and image of a product which can then be viewed on another page. The details will be sent to a mongo database which will be performed via an axios post from the front end. I can send the name and the price no problem which can be seen on the front end dynamically, however, I am unable to send image to the mongo database which i've been trying to achieve now for quite some time.
I am using multer and axios to try and sent the file over as the application is a react app. I think the problem is to do with the "req.file" within the back end of the application. The code below is my endpoint:
api.js
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors')
var app = express();
var mongodb = require('mongodb');
var path = require('path');
var fsextra = require('fs-extra');
var fs = require('fs')
var util = require('util')
var multer = require('multer')
var upload = multer( {dest: __dirname + '/uploads'} )
var ejs = require('ejs')
const MongoClient = require('mongodb').MongoClient;
app.use(express.static(path.resolve(__dirname, '../react', 'build')));
app.get('*',(req,res)=>{
res.sendFile(path.resolve(__dirname, '../react', 'build', 'index.html'));
});
console.log(__dirname)
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', __dirname);
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
var db;
mongodb.MongoClient.connect('mongodb://<mydbdetails>', (err, database) => {
if (err) {
console.log(err)
process.exit(1);
}
db = database;
console.log('Database connection is ready')
});
var server= app.listen(process.env.PORT || 8082, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
app.post('/api/submitImage', upload.single('inputForm'), function(req,res){
var file = req.body.file
if (file == null) {
// If Submit was accidentally clicked with no file selected...
//res.render('admin', { title:'Please select a picture file to submit!'});
res.send({success: false, message: "dsfdsg"})
console.log('There is no file present')
console.log(req.file,'file')
}
else{
// read the img file from tmp in-memory location
var newImg = fs.readFileSync(req.files.path);
console.log(newImg,'details of the new image')
// encode the file as a base64 string.
var encImg = newImg.toString('base64');
console.log(encImg,'kdfjndodj')
// define your new document
var newItem = {
description: req.body.description,
contentType: req.file.mimetype,
size: req.files.size,
img: Buffer(encImg, 'base64')
};
db.collection('products').insert(newItem, function(err, result){
if(err) {
console.log(err)
}
var newoid = new ObjectId(result.ops[0]._id);
fs.remove(req.file.path, function(err) {
if (err) { console.log(err) };
res.render('./src/components/adminContainer.js', {title:'Thanks for the Picture!'});
});
})
}
})
The next code is the how I am trying to send it over using Axios:
import axios from 'axios';
class ProductsApi {
static submitProduct(name,prices,callback){
axios.post('http://localhost:8082/api/submitProduct', {name: name, prices: prices})
.then( response => {
callback(response)
})
}
static viewName(callback){
axios.post('http://localhost:8082/api/retrieveName')
.then( response => {
return callback(response)
})
}
static viewPrice(callback){
axios.post('http://localhost:8082/api/retrievePrice')
.then( response => {
return callback(response)
})
}
static viewProducts(callback){
axios.post('http://localhost:8082/api/retrieveProducts')
.then( response => {
return callback(response)
})
}
static submitImages(image,callback){
axios.post('http://localhost:8082/api/submitImage',{image: image})
.then( response => {
return callback(response)
console.log('response has been made,', image,'has been recieved by axios')
})
}
}
export default ProductsApi;
The last file is how I am trying to send the file to the database using react with event handlers:
import React, { Component } from 'react'
import '../App.css'
import AppHeader from './appHeader.js'
import ProductsApi from '../api/axios.js'
const AdminContainer = () => {
return(
<div>
<AppHeader />
<FormContainer />
</div>
)
}
class FormContainer extends Component{
constructor(props){
super(props);
this.state={
file: '',
inputName: '',
inputPrice: '',
image: ''
};
this.handleNameChange = this.handleNameChange.bind(this);
this.handlePriceChange = this.handlePriceChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.sendName = this.handleSubmit.bind(this);
}
handleNameChange(e){
console.log(e.target.value)
this.setState({
name : e.target.value,
})
}
handlePriceChange(e){
console.log(e.target.value)
this.setState({
prices : e.target.value
})
}
sendName(e){
this.setState({
inputName: e.target.value,
inputName:e.target.value
})
}
handleSubmit(e){
e.preventDefault();
console.log('attempting to access axios...')
ProductsApi.submitProduct(this.state.name, this.state.prices, resp => {
console.log('response has been made', resp)
//if error message, add to state and show error message on front end
this.setState({
inputName:this.state.name,
inputPrice:this.state.prices
},function(){
console.log(resp,'this is resp')
console.log('Axios has send ',this.state.name,' to the database')
});
})
console.log(this.state.prices,'This is the new price')
console.log(this.state.name,'This is the new name')
ProductsApi.submitImages(this.state.image, response => {
console.log('axios has been notified to submit an image...')
this.setState({
image: this.state.image
},function(){
console.log('Image submission axios response details are as follows: ', response)
console.log(this.state.image, ': has been sent to the db')
})
})
}
render(){
return(
<div>
<h2>Add a new product to the Shop</h2>
<div className='formWrapper'>
<div className='center'>
<form name='inputForm' encType='multipart/form-data' method='post'>
<label>
Name:
<input value = {this.state.name} onChange={this.handleNameChange} type="text" placeholder='Name' /><br />
Price:
<input value = {this.state.prices} onChange={this.handlePriceChange} type='text' /><br />
</label>
<label>
Choose an Image:
<input className='imgInsert' name ='inputForm' type='file'/>
</label>
<div>
<img className = 'previewImage' value={this.state.image}/>
</div>
<button className='btn updateBtn' onClick={(e) => this.handleSubmit(e)}>Submit</button>
</form>
</div>
</div>
</div>
)
}
}
export default AdminContainer
Common errors I am getting when trying debug it is
TypeError: Cannot read property 'path' of undefined."
and "file" being undefined.
When using multer to save images you need to make sure that the image comes to the server as form data. this is because multer requires the multipart/form-data encoding which you do not get when submitting a form with an ajax request unless if you specifically do something to make it happen.
You can do this by using the FormData object. Here is an example of this being used. I hope this helps.
I am beginner in Mean stack I am developing an API that fetches all records from mongodb using express. But I am not able to fetch all records from the database. I can't figure what I am doing wrong, I am doing it as follows:
This is my main app (server.js)
require('rootpath')();
var express = require('express');
var app = express();
var session = require('express-session');
var bodyParser = require('body-parser');
var expressJwt = require('express-jwt');
var config = require('config.json');
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
app.use(session({
secret: config.secret,
resave: false,
saveUninitialized: true
}));
// use JWT auth to secure the api
app.use('/api', expressJwt({
secret: config.secret
}).unless({
path: ['/api/users/authenticate', '/api/users/register']
}));
// routes
app.use('/', require('./controllers/login.controller'));
app.use('/register', require('./controllers/register.controller'));
app.use('/app', require('./controllers/app.controller'));
app.use('/api/users', require('./controllers/api/users.controller'));
/*// make '/app' default route
app.get('/', function (req, res) {
return res.redirect('/app');
});*/
// start server
var server = app.listen(3000, function() {
console.log('Server listening at http://' + server.address().address + ':' + server.address().port);
});
This is my user.controller.js user will make a request to the api
http://localhost:3000/api/users/userList
var express = require('express');
var router = express.Router();
var userService = require('services/user.service');
router.get('/userList', getUserList);
module.exports = router;
function getUserList(req, res) {
userService.userList()
.then(function(users) {
if (users) {
res.send(users);
} else {
res.sendStatus(404);
}
})
.catch(function(err) {
res.status(400).send(err);
});
}
This is my user.service.js where I am querying the database to fetch all records using mongoskin driver.
var Q = require('q');
var mongo = require('mongoskin');
var db = mongo.db("mongodb://localhost:27017/EmployeeForm", {
native_parser: true
});
db.bind('users');
var service = {};
service.userList = userList;
module.exports = service;
function userList() {
var deferred = q.defer();
db.users.find(function(err, users) {
if (err) deferred.reject(err.name + ': ' + err.message);
});
return deferred.promise;
}
So i think it's find issue.
MongoDB find method return cursor by default.
https://docs.mongodb.com/manual/reference/method/db.collection.find/
From https://github.com/kissjs/node-mongoskin they use method toArray which will transform cursor into array of objects like this
db.find.toArray(callback)
So try like this in userList()
function userList() {
var deferred = q.defer();
db.users.find({}).toArray(function(err,docs){
err ? deferred.reject(err) : deferred.resolve(docs);
});
return deferred.promise;
}
Hope this helps.
I am learning MongoDB with Youtube video(https://youtu.be/uX2G7Rt51WI?list=PLRQuJcU2aZG-aMedJxa7p7ylYmOn5iMlS) which I am following his code.
I don't think I made typo and I just think I missed some part but I don't know which part I missed.
I think he may create doc file somewhere in MongoDB, but I don't know where and how he made.
This is my code.
var http = require('http'),
express = require('express'),
app = express(),
cons = require('consolidate'),
MongoClient = require('mongodb')
.MongoClient,
Server = require('mongodb')
.Server;
app.engine('html', cons.swig);
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
var mongoclient = new MongoClient(new Server('localhost', 27017, {
'native_parser': true
}));
var db = mongoclient.db('course');
app.get('/', function (req, res) {
db.collection('hello_mongo_express')
.findOne({}, function (req, res) {
res.render('hello', doc);
});
});
mongoclient.open(function (err, mongoclient) {
if (err) throw err;
app.listen(9000, function (req, res) {
console.log('connecting 9000');
});
});
You can easily create a document. After the following line:
var db = mongoclient.db('course');
Add:
db.collection('hello_mongo_express').insert({ comment: 'This is cool'});
Does anyone know how to connect to MongoDb while using the Hapi.js framework?
I have only managed to find one example (https://github.com/Marsup/hapi-mongodb), but this requires using a plugin and has no comments in the code!
Does anyone know of a simpler way?
The following (using mongoose) works pretty well for me:
var Hapi = require('hapi');
var mongoose = require("mongoose");
var server = new Hapi.Server();
server.connection({ port: 3000 });
var dbUrl = 'mongodb://localhost:27017/mydb';
var dbOtions = {
db: { native_parser: true },
server: { poolSize: 5 }
};
server.register([ /* plugins */], function (err) {
if (err) {
throw err; // something bad happened loading the plugins
}
// ... Register the routes
server.start(function () {
mongoose.connect(dbUrl, dbOtions, function(err) {
if (err) server.log('error', err);
});
});
});
I use a hapi plugin that I wrote that connects to mongo, handles errors to log and adds bluebird promises.
'use strict';
var bluebird = require('bluebird');
var mongoose = bluebird.promisifyAll(require('mongoose'));
exports.register = function(plugin, options, next) {
mongoose.connect(options.mongo.uri, options.mongo.options, function (e) {
if (e) {
plugin.log(['error', 'database', 'mongodb'], 'Unable to connect to MongoDB: ' + e.message);
process.exit();
}
mongoose.connection.once('open', function () {
plugin.log(['info', 'database', 'mongodb'], 'Connected to MongoDB # ' + options.mongo.uri);
});
mongoose.connection.on('connected', function () {
plugin.log(['info', 'database', 'mongodb'], 'Connected to MongoDB # ' + options.mongo.uri);
});
mongoose.connection.on('error', function (e) {
plugin.log(['error', 'database', 'mongodb'], 'MongoDB ' + e.message);
});
mongoose.connection.on('disconnected', function () {
plugin.log(['warn', 'database', 'mongodb'], 'MongoDB was disconnected');
});
});
return next();
};
exports.register.attributes = {
name: 'mongoose',
version: '1.0.0'
};
Blog post on user authentication with passport and Mongoose
Also be aware that Hapi's model is based off of plugins so read and re-read the docs on building your own.
Visit http://cronj.com/blog/hapi-mongoose
Complete sample project which can help you Repo Link https://github.com/gauravgupta90/Hapi-Mongoose-Angular
Config.js
module.exports = {
server: {
host: '0.0.0.0',
port: 8000
},
database: {
host: '127.0.0.1',
port: 27017,
db: 'DatabaseName',
username: '',
password: ''
}
};
Server.js
var Hapi = require('hapi'),
Routes = require('./routes'),
config = require('./config'),
Db = require('./database');
var server = Hapi.createServer(config.server.host, config.server.port, {
cors: true
});
server.route(Routes.endpoints);
server.start(function() {
console.log('Server started ', server.info.uri);
});
Database.js
var Mongoose = require('mongoose'),
config = require('./config');
Mongoose.connect('mongodb://' + config.database.host + '/' + config.database.db);
var db = Mongoose.connection;
db.on('error', console.error.bind(console, 'connection error'));
db.once('open', function callback() {
console.log("Connection with database succeeded.");
});
exports.Mongoose = Mongoose;
exports.db = db;
The following works for me:
const Hapi = require("hapi");
const Mongoose = require("mongoose");
const server = new Hapi.Server({ "host": "localhost", "port": 3000 });
Mongoose.connect('mongodb://localhost:27017/testdb', { useNewUrlParser: true }, (err) => {
if (!err) { console.log('MongoDB Connection Succeeded.') }
else { console.log(`Error in DB connection : ${err}`)}
});