Trying to redirect user on valid contact form submission - forms

Hi so I'm trying to make my page redirect to 'confirmationpage.html' only when all the fields are correctly entered. This is my Javascript, how would I go about doing this?
const form = document.getElementById('form');
const name = document.getElementById('name');
const email = document.getElementById('email');
const subject = document.getElementById('subject');
const text = document.getElementById('text');
form.addEventListener('submit', function(e) {
e.preventDefault();
checkInputs();
});
function checkInputs() {
// get values from the inputs
const nameValue = name.value.trim();
const emailValue = email.value.trim();
const subjectValue = subject.value.trim();
const textValue = text.value.trim();
if(nameValue === '') {
// show error message
// add error class
setErrorFor(name, 'Name cannot be blank');
} else {
// add success class
setSuccessFor(name);
}
if(emailValue === '') {
setErrorFor(email, 'Email cannot be blank');
} else if(!isEmail(emailValue)) {
setErrorFor(email, 'Please enter a valid email address');
} else {
setSuccessFor(email);
}
if(subjectValue === '') {
setErrorFor(subject, 'A subject is required');
} else {
setSuccessFor(subject);
}
if(textValue === '') {
setErrorFor(text, 'Please add some text');
} else {
setSuccessFor(text);
}
}
function setErrorFor(input, message) {
const formControl = input.parentElement; // .form-control
const small = formControl.querySelector('small');
// add error message
small.innerText = message;
// add error class
formControl.className = 'form-control error';
}
function setSuccessFor(input) {
const formControl = input.parentElement;
formControl.className = 'form-control success';
}
function isEmail(email) {
return /^(([^<>()[\]\\.,;:\s#"]+(\.[^<>()[\]\\.,;:\s#"]+)*.test(email);
}
Any help would be very appreciated! I'm very new to webpage design and I've been struggling a lot recently

Related

disabled submit button after submitting form data to server. in react native

I am new to react native. I have created a form from where I am sending some data to server. Now I want that to disabled submit button after user click on submit . once user submit data then after He unable to send data. means I want to avoid duplicate entry. please help. thanks. if possible also tell how to do it with functional component too.
here is my code
export default function Add(props) {
const { navigation } = props
const offset = (Platform.OS === 'android') ? -200 : 0;
const [AmazonError, setAmazonError] = useState([]);
const [Amazon, setAmazon] = useState('');
const [AmazonCNError, setAmazonCNError] = useState([]);
const [AmazonCN, setAmazonCN] = useState('');
const [AEPSError, setAEPSError] = useState([]);
const [AEPS, setAEPS] = useState('');
const [DMTError, setDMTError] = useState([]);
const [DMT, setDMT] = useState('');
const [BBPSError, setBBPSError] = useState([]);
const [BBPS, setBBPS] = useState('');
const [leadTagNumber, setLeadTagNumber] = useState([]);
const validateInputs = () => {
if (!Amazon.trim()) {
setAmazonError('Please Fill The Input')
return;
}
if (!AmazonCN.trim()) {
setAmazonCNError('Please Fill The Input')
return;
}
if (!AEPS.trim()) {
setAEPSError('Please Fill The Input')
return;
}
if (!DMT.trim()) {
setDMTError('Please Fill The Input')
return;
}
if (!BBPS.trim()) {
setBBPSError('Please Fill The Input')
return;
}
else
{
//+++++++++++++++++++++++++++++++++=submitting form data to api start+++++++++++++++++++++++++++++++++++
{
const leadTagNumber = props.route.params.leadTagNumber
AsyncStorage.multiGet(["application_id", "created_by",'leadTagNumber']).then(response => {
// console.log(response[0][0]) // Key1
console.log(response[0][1]) // Value1
// console.log(response[1][0]) // Key2
console.log(response[1][1]) // Value2
console.log(leadTagNumber)
fetch('https://xyxtech/Android_API_CI/uploaddata/tbservice_details', {
method: 'POST',
headers: {'Accept': 'application/json, text/plain, */*', "Content-Type": "application/json" },
// We convert the React state to JSON and send it as the POST body
body: JSON.stringify([{ data}])
})
.then((returnValue) => returnValue.json())
.then(function(response) {
console.log(response)
Alert.alert("File uploaded");
return response.json();
});
});
// event.preventDefault();
}
//+++++++++++++++++++++++++++++++++submitting form data to api end++++++++++++++++++++++++++++++++++++++
Alert.alert("success")
return;
//}
}
};
const handleAmazon = (text) => {
setAmazonError('')
setAmazon(text)
}
const handleAmazonCN= (text) => {
setAmazonCNError('')
setAmazonCN(text)
}
const handleAEPS= (text) => {
setAEPSError('')
setAEPS(text)
}
const handleDMT = (text) => {
setDMTError('')
setDMT(text)
}
const handleBBPS = (text) => {
setBBPSError('')
setBBPS(text)
}
return (
<View style={{flex: 1}}>
<ScrollView style={{flex: 1,}} showsVerticalScrollIndicator={false}>
<TextInput
maxLength={30}
placeholder="AEPS (Adhar enabled payment system) *"
style={styles.inputStyle}
onChangeText={(text)=>handleAEPS(text)}
defaultValue={AEPS}
value = {AEPS} />
<Text>{AEPSError}</Text>
</ScrollView>
<Button
style={styles.inputStyleB}
title="Submit"
color="#FF8C00"
onPress={() => validateInputs()}
/>
</View>
)
}
Set new state property to enable/disable button
const [disableButton, setDisableButton] = useState(false);
Now in your button component, add disabled property with disableButton state.
<Button
style={styles.inputStyleB}
title="Submit"
color="#FF8C00"
onPress={() => validateInputs()}
disabled={disableButton}
/>
Disable you button before fetching data
setDisableButton(true) //Add this
const leadTagNumber = props.route.params.leadTagNumber
Incase of fetch error or after fetching is complete, enable button again
setDisabledButton(false)

How can I call req.flash() from inside the mongoose save function?

Upon finding duplicate user entries in my database, I want to flash a message to the view using req.flash(). However, the only parameters allowed in the User.save() function are errors and the results of the save. How can I get the request object in there too so that if there is
an error (i.e. duplicate entry), the user is notified?
requires
const express = require('express')
const router = express.Router()
const mongoose = require('mongoose')
const Quote = require('../models/quotes')
const User = require('../models/users')
const ObjectId = mongoose.Types.ObjectId;
const expressValidator = require('express-validator')
const flash = require('express-flash-messages')
const passport = require('passport')
const bcrypt = require('bcrypt')
const saltRounds = 10
get request:
/* route handling for SIGNUP page. */
router.get('/signup', (req, res, next) => {
const flashMessages = res.locals.getMessages()
console.log('flash:', flashMessages)
if (flashMessages.error) {
console.log('flash:', flashMessages)
res.render('signup', {
showErrors: true,
signupErrors: flashMessages.error
})
} else {
console.log('no flash errors detected.')
res.render('signup')
}
})
post request:
/* route handling for submission to SIGNUP page */
// this is all just front end validation, with no relation to the database. I think flash messages use that
router.post('/signup/users', (req, res, next) => {
req.checkBody('username', 'Username field cannot be empty.').notEmpty()
req.checkBody('username', 'Username must be between 4-30 characters long.').len(4, 30)
req.checkBody('email', 'The email you entered is invalid, please try again.').isEmail()
req.checkBody('email', 'Email address must be between 4-100 characters long, please try again.').len(4, 100)
req.checkBody('password', 'Password must be between 8-100 characters long.').len(8, 100)
// req.checkBody('password', 'Password must include one lowercase character, one uppercase character, a number, and a special character.').matches(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.* )(?=.*[^a-zA-Z0-9]).{8,}$/, 'i')
req.checkBody('passwordMatch', 'Password must be between 8-100 characters long.').len(8, 100)
req.checkBody('passwordMatch', 'Passwords do not match, please try again.').equals(req.body.password)
// Additional validation to ensure username is alphanumeric with underscores and dashes
req.checkBody('username', 'Username can only contain letters, numbers, or underscores.').matches(/^[A-Za-z0-9_-]+$/, 'i')
const errors = req.validationErrors()
if(errors || flashMessages.error) {
res.render('signup', {
errors: errors,
showErrors: true,
signupErrors: flashMessages.error
})
} else {
let password = req.body.password
bcrypt.hash(password, saltRounds, (err, hash) => {
user = new User()
user.username = req.body.username
user.email = req.body.email
user.password = hash
// PROBLEM STARTS HERE
user.save((err, result) => {
if(err) {
// add flash message here to let user know something was wrong!
const flashMessages = res.locals.getMessages()
console.log('flash', flashMessages)
console.log("Your error: ", err.message)
if (err.message.indexOf("duplicate key error") > -1) {
req.flash('signupErrors', "Username already in use.")
console.log(req.flash("hi"))
res.redirect('/signup')
console.log("Made it down here.")
} else {
req.flash('signupErrors', "There was a problem with your registration.")
console.log("Made it wayyyyyy down here.")
res.redirect('/signup')
}
// AND ENDS HERE
} else {
User.find({}).sort({ _id:-1 }).limit(1)
.exec((err, newuser) => {
if (err) {
console.log(err)
} else {
// logins user through passport function
req.login(newuser[0], (err) => {
if (err) {
console.log("Login error 1: " + err)
console.log("Login error 2: " + newuser[0])
console.log("Login error 3: " + newuser[0]._id)
} else {
console.log("Login sucess BULK: " + newuser[0])
console.log("Login success ._id: " + newuser[0]._id)
res.redirect('/home')
}
})
}
})
.catch(next)
}
})
})
}
})
/* route handling for submission to LOGIN page */
router.post('/login/users', passport.authenticate('local', {
successRedirect: '/profile',
failureRedirect: '/login',
failureFlash: true
}))

Accounts.createUser without username, password and email

My application is built with React, which is completely separate from Meteor. I use Asteroid to interface to Meteor which serves as backend only. I have manually created the Facebook login button at front end and want to pass the data fetched from Facebook to Accounts.createUser. This method asks for two parameters which is not available because I have formatted it like so:
const data = {
services: {
facebook: fb
},
profile: {
first_name: fb.first_name,
last_name: fb.last_name,
}
}
I have created a method as below but I failed to log the user in with appropriate token or what ever indicator that Meteor needed:
getLoginByExternalService(options) {
if (Meteor.userId()) throw new Meteor.Error('400',`Please logout ${Meteor.userId()}`);
const email = options.services.facebook.email
const facebookId = options.services.facebook.id
const user = {services: {}}
user.services = options.services
const users = Meteor.users.find({"services.facebook.id": facebookId}).fetch();
if (!users.length) {
const userId = Accounts.insertUserDoc(options, user)
if (Meteor.isServer)
this.setUserId(userId)
else
Meteor.setUserId(userId)
return userId
} else {
if (Meteor.isServer)
this.setUserId(users[0]._id)
if (Meteor.isClient)
Meteor.setUserId(userId)
return {users, userId: Meteor.userId()}
}
}
How to properly log the user in?
Okay I already got the answer. I don't have to format the data return from facebook response. So here the implementation at the backend
getLoginByExternalService(resp) {
if (Meteor.userId()) Meteor.logout(Meteor.userId()) //who knows?
const accessToken = resp.accessToken
const identity = getIdentity(accessToken)
const profilePicture = getProfilePicture(accessToken)
const serviceData = {
accessToken: accessToken,
expiresAt: (+new Date) + (1000 * resp.expiresIn)
}
const whitelisted = ['id', 'email', 'name', 'first_name', 'last_name', 'link', 'username', 'gender', 'locale', 'age_range']
const fields = _.pick(identity, whitelisted)
const options = {profile: {}}
const profileFields = _.pick(identity, getProfileFields())
//creating the token and adding to the user
const stampedToken = Accounts._generateStampedLoginToken()
//hashing is something added with Meteor 0.7.x,
//you don't need to do hashing in previous versions
const hashStampedToken = Accounts._hashStampedToken(stampedToken)
let ref = null
_.extend(serviceData, fields)
_.extend(options.profile, profileFields)
options.profile.avatar = profilePicture
try {
ref = Accounts.updateOrCreateUserFromExternalService("facebook", serviceData, options);
} catch (e) {
if (e.reason === "Email already exists.") {
const existingUser = Meteor.users.findOne({ 'emails.address': identity.email })
if ( existingUser ) {
if ( identity.verified ) {
Meteor.users.update({ _id: existingUser._id }, { $set: { 'services.facebook': serviceData }})
ref = { userId: existingUser._id }
console.log(`Merged facebook identity with existing local user ${existingUser._id}`);
} else {
throw Meteor.Error(403, "Refusing to merge unverified facebook identity with existing user")
}
}
} else {
throw Meteor.Error(e.error, e.reason)
}
}
Meteor.users.update(ref.userId, {$push: {'services.resume.loginTokens': hashStampedToken}})
return {id: ref.userId, token: stampedToken.token}
}
so somewhere at the front end
asteroid.call("getLoginByExternalService", data).then(response => response)

What does this `checkSession` function do?

I have included the firebase and angularfire libraries to my ionic framework project.
I am following the below link for my sample project.
https://www.sitepoint.com/creating-firebase-powered-end-end-ionic-application/
I am not able to understand how the 'checkSession' function in the below 'app.js' works. Could someone please explain?
How can we call the 'auth' function which is inside 'checkSession' function?
app.js
angular.module('bucketList', ['ionic', 'firebase', 'bucketList.controllers'])
.run(function($ionicPlatform, $rootScope, $firebaseAuth, $firebase, $window, $ionicLoading) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
StatusBar.styleDefault();
}
$rootScope.userEmail = null;
$rootScope.baseUrl = 'https://bucketlist-app.firebaseio.com/';
var authRef = new Firebase($rootScope.baseUrl);
$rootScope.auth = $firebaseAuth(authRef);
$rootScope.show = function(text) {
$rootScope.loading = $ionicLoading.show({
content: text ? text : 'Loading..',
animation: 'fade-in',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
});
};
$rootScope.hide = function() {
$ionicLoading.hide();
};
$rootScope.notify = function(text) {
$rootScope.show(text);
$window.setTimeout(function() {
$rootScope.hide();
}, 1999);
};
$rootScope.logout = function() {
$rootScope.auth.$logout();
$rootScope.checkSession();
};
$rootScope.checkSession = function() {
var auth = new FirebaseSimpleLogin(authRef, function(error, user) {
if (error) {
// no action yet.. redirect to default route
$rootScope.userEmail = null;
$window.location.href = '#/auth/signin';
} else if (user) {
// user authenticated with Firebase
$rootScope.userEmail = user.email;
$window.location.href = ('#/bucket/list');
} else {
// user is logged out
$rootScope.userEmail = null;
$window.location.href = '#/auth/signin';
}
});
}
});
})

unique form field validation in extjs4

Is there a cleaner way to define unique form field in extjs. Below is a sample code that is checking on client UID on client creation/edition. This code is working but has some bugs - for example on client creation if you enter a value that is already present in DB validator returns true until you unfocus the field.
Ext.define('AM.view.client.UniqueField', {
extend: 'Ext.form.field.Text',
alias : 'widget.uniquefield',
vtype: 'UniqueUid',
initComponent: function() {
Ext.apply(Ext.form.field.VTypes, {
UniqueUidMask : /[0-9]/i,
UniqueUid : function(val,field) {
if (val.length < 9) {
Ext.apply(Ext.form.field.VTypes, {
UniqueUidText: 'Company ID is too small'
});
return false;
} else {
var paste=/^[0-9_]+$/;
if (!paste.test(val)) {
Ext.apply(Ext.form.field.VTypes, {
UniqueUidText: 'Ivalid characters'
});
return false;
} else {
var mask = new Ext.LoadMask(field.up('form'),{msg:'Please wait checking....'});
mask.show();
var test= 0;
var store = Ext.create('AM.store.Clients');
store.load({params:{'uid':val, 'id': Ext.getCmp('client_id').getValue()}});
store.on('load', function(test) {
mask.hide();
if(parseInt(store.getTotalCount())==0){
this.uniqueStore(true);
}else{
Ext.apply(Ext.form.field.VTypes, {
UniqueUidText: 'Company ID is already present'
});
this.uniqueStore(false);
}
},this)
return true;
}
}}
},this);
this.callParent(arguments);
},
uniqueStore: function(is_error){
Ext.apply(Ext.form.field.VTypes, {
UniqueUidMask : /[0-9]/i,
UniqueUid : function(val,field) {
if (val.length < 9) {
Ext.apply(Ext.form.field.VTypes, {
UniqueUidText: 'Company ID is too small'
});
return false;
} else {
var paste=/^[0-9_]+$/;
if (!paste.test(val)) {
Ext.apply(Ext.form.field.VTypes, {
UniqueUidText: 'Ivalid characters'
});
return false;
} else {
var mask = new Ext.LoadMask(field.up('form'),{msg:'Please wait checking....'});
mask.show();
var store = Ext.create('AM.store.Clients');
store.load({params:{'uid':val, 'id': Ext.getCmp('client_id').getValue()}});
store.on('load', function(test) {
mask.hide();
if(parseInt(store.getTotalCount())==0){
this.uniqueStore(true);
}else{
this.uniqueStore(false);
}
},this)
return is_error;
}
}}
},this);
}
});
How about using server side validation?
I answered to similar issue here: extjs4 rails 3 model validation for uniqueness
Obviously you can change it to use "ajax" instead of "rest" proxy.