Why do I need to refresh the page to get the newly-updated data? - node.js

I was making an application including a comment function with "likes" and "dislikes" just like Facebook. But I find when users click the button of "like" or "dislike", everything goes well --- the database has been updated and the new data has been rendered back to previous webpage, except users need to refresh the page manually to get the new webpage with newly-updated data. Here are my files (I just take the codes of "like" function as example, the codes of "dislike" function is the same):
JS codes:
$("#scrollit").on("click", ".fa-thumbs-up", function(){
var numberOfLikes = Number($(this).next().html());
var numberOfDislikes = Number($(this).next().next().next().html());
numberOfLikes = numberOfLikes + 1;
var Text = $(this).next().next().next().next().next().html();
console.log(Text);
$.ajax({
method: "POST",
url: "/searchresult/comments/likes",
data: {text:Text, likes: numberOfLikes, dislikes: numberOfDislikes}
});
});
Node.js codes:
app.post("/searchresult/comments/likes", function(req, res) {
var likes = req.body.likes;
var Text = req.body.text;
new Promise(function(resolve, reject) {
comments.update({text: Text}, {$set: {likes: likes}}, function(err){
if (err) {
console.log(err);
} else {
console.log("Likes update successfully!");
resolve(comments);
}
});
}).then(function(r){
console.log("DONE!");
res.redirect("/searchresult");
});
});
app.get("/searchresult", function(req, res){
var EnglishofWord = EnglishofWords[EnglishofWords.length - 1];
grewords.findOne({English: EnglishofWord}).populate("Comments").exec(function(err, allgrewords){
if (err) {
console.log(err);
} else {
console.log(allgrewords);
if (allgrewords == null || allgrewords.length < 1 || allgrewords == undefined ) {
console.log("We don't have this word in dictionary!");
res.render("errorpage");
} else {
res.render("searchresult", {greword:allgrewords});
}
}
});
});
ejs codes:
<% greword.Comments.forEach(function(comment){ %>
<strong><p class="author"><%= comment.author %></p></strong>
<i class="far fa-thumbs-up"></i><span class="likes"><%= comment.likes %></span>
<i class="far fa-thumbs-down"></i><span class="dislikes"><%= comment.dislikes%></span>
<span class="pull-right">10 days ago</span>
<p><%= comment.text %></p>
<% }) %>
Could anybody help me to figure it out? ---- Why doesn't the webpage refresh itself automatically? Thanks so much! :P
//************************************************ Update! ***************************************************//
Thanks a lot to t3__rry, his/her suggestion was enlightening! Now I have made it work properly.

Related

fetch users data from database in node

I am currently learning nodeJS and I am able to make a user connect or disconnect to a user area, but I would like to display his infos from the database and I'm not sure how I can proceed
app.get('/profil', function(request, response) {
// If the user is loggedin
if (request.session.loggedin) {
// show the home page of logged users
username = request.session.username
catfood = request.session.catfood
password = request.session.password
email = request.session.email
var sql = "SELECT * FROM accounts WHERE username = '"+ username + "'";
connection.query( sql, function ( err, resultSet ) {
if ( err ) throw err;
//console.log( resultSet );
catfood = resultSet[0].catfood;
});
//connection.end();
response.render('loggedin/profil', )
response.end();
} else {
// Not logged in
response.send('Please login to view this page! login');
}
response.end();
});
profil.ejs :
<div class="max-w-screen-lg bg-white shadow-2xl rounded-lg mx-auto text-center py-12 mt-4">
<h2 class="text-3xl leading-9 font-bold tracking-tight text-red-800 sm:text-4xl sm:leading-10">
<%= I would like to display, like, his username, etc %>
</h2>
I am normally a PHP dev, but trying to learn a new back end language.
For example, in PHP, you would do :
$req = $bdd->prepare("SELECT * FROM users WHERE username = :user");
$req->bindValue('user',$username, PDO::PARAM_STR);
$req->execute();
$user = $req->fetch(PDO::FETCH_OBJ);
echo $user->username;
How to do the same in nodeJS ?
You should do render with in the query callback, like this:
connection.query( sql, function ( err, resultSet ) {
if ( err ) throw err;
//console.log( resultSet );
catfood = resultSet[0].catfood;
response.render('loggedin/profil', {catfood: catfood});
response.end();
});
Now you can use the catfood object in your template.
I managed to do it.
You had to:
app.js:
var sql = "SELECT * FROM drops WHERE username = '"+ username + "'";
connection.query(sql, function (err, resultSet) {
response.render('loggedin/index', {
user: resultSet
});
});
index.js:
<% user.forEach(function(o) { %>
<%= o.username %> - <%= o.cat %> <br>
<% }); %>
without the loop if you don't need to go through a loop

HTML from database is displayed as plain text

I have a webserver running on NodeJS and ExpressJS. As template engine I am using EJS.
There's a database where I store posts and some of these include html tags such as <b><i><u>. Before the posts are uploaded to the database; They are trim() & escape() -ed. Also unwanted tags are stripped away.
The problem is that when I fetch posts from db, send it to the client over expressjs render('template', {options:__, x: _, y: _}) method, the html is not displayed as its supposed to be. It is displayed as plaintext like so: <b>test</b> instead of test.
Main.js ( script which fetches posts from db )
const express = require('express');
const sql = require('sql');
module.exports = {
runScript: function(callback){
sql.prepareQuery('SELECT `posts`.*, `accounts`.`firstname`, `accounts`.`lastname`, `accounts`.`username` FROM `posts` LEFT JOIN `accounts` ON `posts`.`author_id`=`accounts`.`id` ORDER BY `posts`.`time` DESC LIMIT 20',
{}, function(error, results){
let variables = {
posts:results
}
callback(variables);
});
}
}
Router for main page
router.get('/', function(req, res, next) {
try {
let pageCore = require(__dirname + "/backend/main.js");
pageCore.runScript(function(obj){
res.set({'Content-Type': 'text/html; charset=utf-8'});
res.locals.posts = obj.posts;
res.locals.timeParser = require('timeParser');
res.render('index', {
title:"Express",
pageToDisplay: "main.ejs"
});
});
} catch(e){
console.log("WTF??", e);
res.send(e);
}
});
Main.EJS (html part)
<div class="postBody">
<%= decodeURIComponent(posts[i].content) %>
</div>
I believe this is a print vs eval thing. Try switching your ejs to this instead.
<div class="postBody">
<%- decodeURIComponent(posts[i].content) %>
</div>

How to store credentials in Vue app needed for module requirement

I've developed a Vue app that gets its data from a CouchDB backend only after a user has logged in with the right credentials. The current state requires the user to enter login info every time the browser is reloaded, and also leaves the login info exposed in the browser. I'm looking for a way to save the credentials (as cookies, possibly, and preferably a vue-centric way), so they can be used to require a module that needs them.
The user sees the following HTML, whence the credential info comes.
LandingPage.vue
<div id="wrapper">
<el-dialog :visible="!authenticated">
<div slot="title">LOG IN TO THE DOCUMENTATION REPOSITORY</div>
<el-form inline>
<el-form-item>
<el-input type="text" v-model="username" placeholder="USERNAME"></el-input>
</el-form-item>
<el-form-item>
<el-input type="password" v-model="password" placeholder="PASSWORD"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" :disabled="!(username.length&&password.length)" #click="authenticate">LOG IN</el-button>
</el-form-item>
</el-form>
</el-dialog>
<the-rest-of-the-app v-if="authenticated"></the-rest-of-the-app>
</div>
Here is the authenticate function:
LandingPage.vue
authenticate: function(){
this.authenticated=true
var credentials = [ this.username, this.password ]
var Store = require('../store.js')['default'](credentials)
console.log(Object.keys(Store))
var self = this;
Store.getDB().then(val => {
self.getCategories(Store);
self.handleChange(Store);
self.result = val;
self.$forceUpdate()
}).catch(err => {
console.log(err)
})
},
This causes data to be loaded that is fetched using functions from the Store module. Store looks like this:
store.js
var path = require('path')
var dir = require('node-dir')
var mime = require('mime-types')
export default function(credentials){
var serverName = 'localhost:5984'
var username = credentials[0]
var adminPassword = credentials[1]
var serverUrl = `http://${username}:${adminPassword}#${serverName}`
var nano = require('nano')(serverUrl)
var documentation = nano.use('documentation')
return {
getDB: function(){
return new Promise(function(accept, reject){
nano.db.get('documentation', function(err, body) {
if (!err) {
console.log(body);
accept(body)
}
});
})
},
getCategories: function(){
var self=this
return new Promise(function(accept, reject){
documentation.view('categories', 'list', {"reduce": false}, function(err, body) {
if (!err) {
accept(body.rows)
}
else {
console.log(err)
}
})
})
}
}
Is there a better way to store the credentials so that:
they won't be lost on refresh,
they won't be exposed in the browser for anyone w/ JavaScript access to access?

Getting a "Unexpected field at makeError" when uploading a form

My form has an input for a file (in my case an image) and for some text. When I hit the submit button, the stated error occurs. I have had the issue for two days now and I tried to understand where the problem was, but my efforts were in vain and I have decided to yield and seek assistance.
Here is my controller for the image:
// using this to generate a random name for an image
var possible = 'abcdefghijklmnopqrstuvwxyz0123456789',
imgUrl = '';
// this is just a loop to create a 10 character random name
for(var i = 0; i < 10; i++) {
imgUrl += possible.charAt(Math.floor(Math.random() *
possible.length));
}
/* I saw an answer to a similar question where the correct answer author
said path will always refer to folder where the input folder resides */
var tempPath = req.file.path,
ext = path.extname(req.file.path).toLower(),
targetPath = './app/controller/store/' + imgUrl + ext;
// Check if image is of the correct format
if (ext === '.png' || ext === '.jpg' || ext === '.jpeg' || ext === '.gif')
{
fs.rename(tempPath, targetPath, function(err) {
if (err) throw err;
res.redirect('/posts/'+ imgUrl);
});
} else {
fs.unlink(tempPath, function () {
if (err) throw err;
res.json(500, {error: 'Only image files are allowed.'});
});
var post = new Post({
content: req.body.content,
author: req.user,
filename: imgUrl + ext
});
post.save(function(err) {
if(err) {
return res.status(400).send({
message: getErrorMessage(err)
});
} else res.json(post);
});
}
And here is the form:
<form method="post" action="/posts" enctype="multipart/form-data">
<textarea name="content"></textarea>
<input type="file" name="file" id="file">
<input type="submit" value="Post">
</form>
I did the usual stuff in my configuration file:
app.use(multer({dest: './app/controller/store'}).single('photo'));
I would truly appreciate it if you steer me towards the right path, thanks in advance.
.single('parameter') means the input field's name is 'parameter'
In your case:
app.use(multer({dest: './app/controller/store'}).single('photo'));
You passed a 'photo' argument into single func.
Then your form should look like this, change it:
..
..
<input type="file" name="photo">
..
..

I want to display some query mongoose result data using Angular on an html page

I have a little problem, I want to display some mongoose query result data using Angular on on an html page.
I don't know how to send data to the angular $scope.
app.js:
User.find({ Code: doc.Code}, function (err, data){
var users = [];
var userswithsamecode = '';
data.forEach(function(d){
console.log(d.nom + " " + d.prenom);
users.push(d);
userswithsamecode += "<li>" + d.nom +" "+ d.prenom + '</li><br>';
How can I send this result to the angular $scope,
collegues.html
<html data-ng-app="demo">
<div data-ng-controller="simple">
Name:
<br/>
<input type="text" data-ng-model="name" />
<br/>
<ul>
<li data-ng-repeat="collegue in collegues |filter:name">{{}} </li>
</ul>
</div>
<script src="angular.min.js"></script>
<script>
var demo=angular.module('demo', []);
function simple($scope){
$scope.collegues=
];}
demo.controller('simple', simple);
</script>'
Thanks for your help!
First you need to create a model for mongo. An example
var Example = mongoose.model('ExampleCollection'{
name:String,
description: String
});
//posting to a mongodb
var example = new Example (
app.post("/add-something-to-mongo", function(req, res) {
name: req.body.name,
description: req.body.description
});
listing.save(function(err) {
if(err) {
console.log("Error! ", err);
}else
{
console.log("Saved!"
};
});
});
});
The angular code would look something like this.
var app = this;
var url = "heroku_url or localhost url";
app.save = function(Example) {
// create a new object
var newExample = {
"name": $scope.name
"description": $scope.description
};
$http.post(url + "/routefromserver", newExample).success(function() {
console.log("posting");
})
};
And lastly the HTML
<input id="name" type="text" ng-model="name" />
<input id="city" type="text" ng-model="description"/>
<button ng-click="app.save()">Save Me</button>

Resources