Show errors after page refresh in Express - javascript

I'm learning Node.js with Express. I'm doing some basic form validation. If it fails, I'd like to reload the page with same view showing the errors. For the validation I'm using express-validator.
I am able to display the errors and the same view, but the URL is not that one belonging to the view that has the form, but that one called by the POST request. I'd like to be redirected to the form view with the messages though.
This is my code so far
// process form to add ideas
app.post('/ideas', (req, res) => {
req.checkBody('details', 'Details are required').notEmpty();
var errors = req.validationErrors();
if (errors) {
res.render('ideas/add', {
title: 'Add Ideas',
errors: errors
});
} else {
res.send('ok');
}
});
So, even if I render back the view "ideas/add"... the URL is going to be "/ideas"... but I'd like it were "ideas/add" too.
Any ideas?
Thanks

Related

Rendering something on server side by taking input from frontend

I have been asked to perform following task
Take a code input from frontend, i.e user would give his code on frontend (design for a web/landing page)
On backend we have many fields inside an api route
route.get("/", (req, res) => {
const fullName: "Varun Bindal"
const contactNo = 9293939933
const message = "Message I want to display"
//Many more
}
Tell user a way where when we serve his code such that, he could dynamically access/assign the fields we have in the backend into his code
I did some googling and found the express officially recommends ejs for server side compilation of webpage
Can someone please help me figure out how we can achieve this?
Yes you can!
Firstly you must include ejs in your project, configure it in your server.js file for example, then you can call res.render() in your callback parameter on route.get().
In your html or javascript you can create a placeholder which gets populated.
Example (server):
route.engine('html', ejs.renderFile);
route.engine('js', ejs.renderFile);
route.get('/', (req, res) => res.render(path.resolve(__dirname, '
../ui/index.html'), {
'myVal': 42,
}));
Example (client html, js, etc...):
<%= myVal %>

How create a simple get form that will create a dynamic route, depending on the value of the search field (MONGODB and Node.js)

i want search throw the database for a value that the user puts in a get form.
The backend is very simple, i know how to search throw the database and render the result..
app.get('search/:id', function(req, res) {
var id = req.param("id");
mongoose.model('Something').find({
// the field that i want find. For example:
_id: id // This will search for the id field in the database, them will return a object if finds a match.
}, function(error, object){
if (error) {
res.send(error);
}
else {
res.send(object);
}
}
);
});
This script will work.
Now i'm having problems with the HTML.
I need a get form that will send a user to /search/SOMETHING THAT THE USER WANTS SEARCH, but i don't know exactly how to change the url dinamically..
Any help is very very welcome.
If you don't know how to achieve desired behaviour in the HTML, you could still do it in the backend - by setting a redirect. Your incoming request after form submission would be something like ?inputName=user search string.
You could then take the value of the query and perform an internal redirect to your route
app.get('search', function(req, res) {
res.redirect('/search/' + req.query["inputName"]);
});
to get a form to pass GET params in a nice express-like way, you need to hook on the onSubmit of the form and then trigger an XHR/ajax request instead of the form-post.
Or you can read the querystring via req.query.inputFieldName if you are okay having the url look like /search/?inputFieldName=AwesomeSearchString
I'd take the XHR/ajax way as it also prevents the page from reloading and thus improving user-experience.

Get URL after sending form with webdriverio

I need to automate a sign in process test. I'm using webdriver.io in order to do that.
Here is my problem.
I have this bizarre sign in process:
I have to fulfil a form in a regular webpage
After sending the form, I'll be redirected to an URL that does not exist, but it contains an access code in one of its query params
Then I take this access code and send it to another location to obtain an access token.
What I need is a way of programmatically complete step 2, since 1 and 3 I have already figured out.
I'm trying like this:
var webdriverio = require('webdriverio');
var options = {
desiredCapabilities: {
browserName: 'chrome'
}
};
webdriverio
.remote(options)
.init()
.url(myUrl)
.title(function(err, res) {
console.log('Title was: ' + res.value);
})
.setValue('#usuario', user)
.setValue('#password', password)
.submitForm('form', function(){
this.url(function(err, res){
console.log(res.value);
});
this.pause(5000, function(){
this.end();
});
});
However, it seems like the callback for submitForm is called before the page gets loaded. This way, my log shows the very same URL I passed before.
If I try like this:
.submitForm('form', function(){
this.pause(5000, function(){
this.url(function(err, res){
console.log(res.value);
this.end();
});
});
});
I get this strange output:
data:text/html,chromewebdata
I know that a pause is not flawless in this context, but I could not find an asynchronous way of doing this.
Can anyone help?
You are probably not waiting for specific state after your form is submitted. What is the expected result after the form is submitted?
For example, you are expecting browser to redirect to a page with a header
<h1 class="success">Your form is submitted successfully</h1>
Then you should do something like this:
webdriverio
.remote(options)
.init()
.url(myUrl)
.waitForExist('form')
.setValue('#usuario', user)
.setValue('#password', password)
.submitForm('form')
.waitForExist('h1.success', 5000)
.getText('h1', function (err, res) {
expect(res).to.contain('submitted successfully'); //chai.js
})
.call(done);

Node.js, MongoDB Login form

I have a node.js application with a connection to a remote mongoDB server. The database contains some custom codes that have been pre-created and distributed to certain users. The idea is that only those who enter one of such codes into a form on the index page can be allowed to view the rest of the site. That is, I want to cross-reference the code entered with the master list stored in my database.
This is an example of what I'm trying to do(note this is in routes/index.js):
collection.findOne({ "Code": "fooCode" }, function(err, doc){
if you cannot find fooCode
show an error message, clear the input area and tell the user to re-enter a correct code
if you find fooCode
redirect to a new page;
});
The above code is within a
router.post('/', function(req, res){...})
function.
My question is, how do I clear the text input area(without refreshing the page) and ask the user to re-enter a new code when a wrong code is entered?
Secondly how do I redirect the user to a new page on valid entry of a code? Thanks.
For that kind of behavior you would need to submit the form via XHR, parse the (JSON) response, and then clear the form on error and display error information. On the server side you can simply do something like res.json({ status: 'success' }); or res.json({ status: 'error', error: 'Bad token' });
On success, you could do the redirect in the browser via window.location.replace("http://example.org/foo"); or if you want the current page in the session history (e.g. reachable with the browser's back button) you can use window.location.href = "http://example.org/foo".
To clear the input: I would handle this on the front-end, so that everytime the button is clicked (to send the form) it clears the input with:
<input id="userInput" type="text">
<button id="submitBtn">Send</button>
Then in your script:
// Cache DOM
const myInput = document.getElementById('userInput');
const myBtn = document.getElementById('submitBtn');
// Event Bind
myBtn.on('click', clearInput);
// Functions
function clearInput() {
myInput.value = '';
}
2. To redirect the user to a new page
res.redirect('/<path>');
You can do the following in your routes to redirect user to the home route.
collection.findOne({ "Code": "fooCode" }, function(err, doc){
if err throw err
else {
res.redirect('/');
}
})

Express and realtime apps. Persist updates from client to server to client

I am writing a realtime app. The basic principle is like a chat, but instead of text messages, users share youtube videos. The backend hasn't been completely done yet, and I don't know how I will do it. But I have some questions for what has been done.
Right now, user authentication with user/pass, FB, Twitter works well, and credentials are being stored in my db. User sign in works fine as well. Error messages get flashed fine.
I'm using mongodb (mongoose) and express on the backend. It is not an API based design because I don't know how to work with user authentication in API's (I can make GET/POST/PUT/DELETE API, just don't know how to fit in authentication in there).
When a user, say, signin's using the homepage, the credentials are verified using req.body.<field> in an express.js route. If authenticated, redirect the user to a dashboard, else redirect to signin with flash messages. So, there are no Ajax calls, and right now, the app isn't realtime in any way. I'd like it to be realtime though.
So, leading to that, I have 3 questions:
I am using a modal window (bootstrap), to ask the user to update profile. The modal shows fine, except the field I want to be shown are not shown. The password and email fields are empty, even though I have a value attribute.
input.form-control.dash(type="password", name="newuserpassword", ng-minlength=8, ng-model="password", value="__USE_EXISTING__")
input.form-control.dash(type="email", name="newuseremail", required=true, ng-model="email", value=user.email)
http://snappy-app.com/s/read.php?pass=9fc7ffa1e2b2140aad5232d5733f4caf
I want that when user edits the "Save" button, a message in the modal should either how any errors, or show that the update was successful. As it is, right now, my update method doesn't do this. Beyond redirecting the user, I don't know how can I achieve what I want.
exports.update_user = function(req, res) {
var user = new User({
'username' : req.user.username,
'password': req.body.newuserpassword || ,
'email': req.body.newuseremail
});
console.log(user);
user.save(function(err) {
if (err) {
console.log(err);
for (var field in err.errors) {
var error = err.errors[field].message;
req.flash('error', error);
}
res.redirect('/dashboard');
} else {
req.logIn(user, function (err) {
if (!err) {
req.flash('success', 'Done!');
} else {
req.flash('error', 'Something went wrong.');
}
});
}
});
}
After the user updates the values by clicking "Save", the modal will close. The user can still click on the "Edit" link to change values yet again, and the modal will open. Now, based on what I have read, the user won't see the changes, because there hasn't been a page/modal reload. How do I make sure that the user sees updated values?
Any help is appreciated.
When I read your text, I think:
"Hum, he tried to make an Ajax call and let the view display the errors or go on"
When I read your code, I think:
"Hum, it's a synchrone "give me all the page" call"
Which version do you want?
The Async one? So we can explain you the Ajax principle and your real problem is an UI update.
The Sync one? It's definitively an UI problem, and you should add a tag for it.

Categories