Parse.com - Cannot add additional fields to User - javascript

Just getting started with Parse.com and following their JavaScript ToDo app tutorial and having some issues.
Basically it will work perfectly and post to the Parse database when I just have the Username and Password but if I try to add any additional fields like email or phone, it won't send it to the database. I have already defined both email and phone fields in my Parse database.
Any help would be appreciated. Thanks!
My html for my form:
<script type="text/template" id="login-template">
<header id="header"></header>
<form class="signup-form">
<h2>Sign Up</h2>
<div class="error" style="display:none"></div>
<input type="text" id="signup-username" placeholder="Username" />
<input type="password" id="signup-password" placeholder="Create a Password" />
<input type="email" id="signup-email" placeholder="Email" />
<input type="text" id="signup-phone" placeholder="Phone" />
<button>Sign Up</button>
</form>
</div>
</script>
My JS:
var LogInView = Parse.View.extend({
events: {
"submit form.signup-form": "signUp"
},
el: ".content",
initialize: function() {
_.bindAll(this, "signUp");
this.render();
},
signUp: function(e) {
var self = this;
var username = this.$("#signup-username").val();
var password = this.$("#signup-password").val();
var email = this.$("#signup-email").val();
var phone = this.$("#signup-phone").val();
Parse.User.signUp(username, password, email, phone, { ACL: new Parse.ACL() }, {
success: function(user) {
new ManageTodosView();
self.undelegateEvents();
delete self;
},
error: function(user, error) {
self.$(".signup-form .error").html(error.message).show();
self.$(".signup-form button").removeAttr("disabled");
}
});
this.$(".signup-form button").attr("disabled", "disabled");
return false;
},
render: function() {
this.$el.html(_.template($("#login-template").html()));
this.delegateEvents();
}
});

You should use the following syntax, like specified in the javascript docs (https://parse.com/docs/js_guide):
var user = new Parse.User();
user.set("username",username);
user.set("password",password);
user.set("email",email);
user.set("phone",phone);
user.signUp(null,{
success:function(user){...},
error:function(user,error){...}
});
You can add any fields you want with the set method.

I had to change <!--<button>Submit</button>--> to <!--<input type="submit"></input>--> to get this to work but then it did. Thanks.

Related

Cannot POST / login.html

I'm having trouble sending data to the server using a form. I already made a register form that works just fine, and for the most part my client side javascript for the login form is very similar to the javascript for the register form, and I just can't figure out why it won't work. It just gives me "Cannot POST /login.html"
Here's the login form html:
<div class="loginTitle">
<h1>Login</h1>
</div>
<div class="loginFormLayout">
<form method=post id="loginForm">
<div class="loginFormText">
<label for="username">Username</label>
</div>
<div class="loginFormEntry">
<input type="text" placeholder="Enter Username" name="loginUsername" required>
</div>
<div class="loginFormText">
<label for="password">Password</label>
</div>
<div class="loginFormEntry">
<input type="password" placeholder="Enter Password" name=loginPassword required>
</div>
<button type="submit" class="loginButton">Log In</button>
</form>
</div>
And here's the client side javascript:
//Login as an existing user
const login = document.getElementsByClassName('loginButton');
const loginForm = document.getElementById('loginForm');
const loginURL = 'http://localhost:3000/loginUser';
loginForm.addEventListener('submit', (event) => {
event.preventDefault();
const formData = new FormData(loginForm);
let username = formData.get('loginUsername');
let password = formData.get('loginPassword');
loginForm.reset();
let user = { //Create a user object that will be sent to the backend and compared to the user database
username,
password
};
fetch(loginURL, { //Send the user object to the backend in JSON format to be checked against the database
method: 'POST',
body: JSON.stringify(user),
headers: {
'content-type': 'application/json'
}
})});
And the server side javascript for now, console logs are just to see if the info is getting up to the server
app.post('/loginUser', (req, res) => {
console.log(req.body.username);
console.log(req.body.password);
});
EDIT: I've also decided to post the info for my register form, which DOES work and uses similar logic to the login form. Maybe I'm missing something that isn't in the login logic
Register form html:
<div class="loginMenu">
<div class="loginTitle">
<h1>Register</h1>
</div>
<div id="registerWarning"></div>
<div class="loginFormLayout">
<form method="post" id="registerForm">
<div class="loginFormText">
<label for="username" id="newUsername">Username</label>
</div>
<div class="loginFormEntry">
<input type="text" placeholder="Create Username" name="username" required>
</div>
<div class="loginFormText">
<label for="password" id="newPassword">Password</label>
</div>
<div class="loginFormEntry">
<input type="password" placeholder="Create Password" name=password required>
</div>
<div class="loginFormText">
<label for="confirmPassword">Confirm Password</label>
</div>
<div class="loginFormEntry">
<input type="password" placeholder="Confirm Password" name="confirmPassword" required>
</div>
<button type="submit" class="registerButton">Register</button>
</form>
</div>
</div>
Register form client side javascript:
//Register a new user
const register = document.getElementsByClassName('registerButton');
const registerForm = document.getElementById('registerForm');
const registerURL = 'http://localhost:3000/createNewUser';
//When the user presses the register button, get the info from the form
registerForm.addEventListener('submit', (event) => {
event.preventDefault();
const formData = new FormData(registerForm);
let newUsername = formData.get('username');
let newPassword = formData.get('password');
let confirmPassword = formData.get('confirmPassword')
registerForm.reset();
//Make sure new password and confirm password are equal
if (newPassword == confirmPassword) {
if (newUsername != "" && newPassword != ""){ //Make sure user enters something for both fields
let newUser = { //Create an object to send to the back end
newUsername,
newPassword
};
fetch(registerURL, { //Send the newUser object to the backend in JSON format to be added to the database
method: 'POST',
body: JSON.stringify(newUser),
headers: {
'content-type': 'application/json'
}
});
}
}
else { //If newPassword and confirmPassword are not equal, ask the user to enter them correctly
const registerWarning = document.getElementById('registerWarning');
registerWarning.innerText = 'Password and Confirm Password do not match';
registerWarning.style.padding = "10px";
registerWarning.style.background = 'red';
};
});
Register form server-side javascript:
app.post('/createNewUser', (req, res) => {
let newUsername = req.body.newUsername;
let newPassword = req.body.newPassword;
let newUserData = 'INSERT INTO users (username, password) VALUES (?, ?)';//Use the question marks as placeholders
//Use bcrypt to hash the password before putting it in the database
bcrypt.hash(newPassword, saltRounds, function(err, hash) {
db.query(newUserData, [newUsername, hash], function(err, result) {
if (err) throw err;
console.log('New user registered');
});
});
});
I figured it out, thanks to #Rocky Sims for the help.
Basically, the register form doesn't exist on the login html page, which was throwing an error up about how that doesn't exist before it could even get to the login code. So I just had to make seperate register.js and login.js files, as the issue was due to them being in the same file.
Try wrapping your form method (post) in quotes ('') like so <form method='post' id="loginForm">
Also the value for the name attribute for your password input should by in quotes. Like so <input type="password" placeholder="Enter Password" name='password' required>
I think the problem is that you haven't told the server what to send back to the client when the POST /loginUser endpoint gets called. Try adding res.sendStatus(200); at the end of your POST /loginUser handler function (so right after console.log(req.body.password);).

Login page in Oracle jet

Hi I am creating an application using Oracle JET in which after I click the Login button in the LoginTest page, it should take me to the Homepage after validation. I have managed to validate the input but I couldn't route it to the Homepage. I have tried using multiple binding but it is of no use. Could someone please help.
HTML CODE
h1>logintest</h1>
<div align="center">
<label for="username">Username</label>
<input id="username" type="text" required
data-bind="ojComponent: {component: 'ojInputText',
validators: [{type: 'regExp', options: {pattern: '[a-zA-Z0-9]{3,}',
messageDetail: 'You must enter at least 3 letters or numbers'}}],
invalidComponentTracker: tracker}" /><br /><br />
<label for="password">Password</label>
<input id="password" type="password" required
data-bind="ojComponent: {component: 'ojInputPassword',
validators: [{type: 'regExp', options : {pattern: '(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{6,}',
messageSummary : '{label} too Weak',
messageDetail: 'The password must contain atleast one uppercase, one lowercase, one number and must be 6 digits long'}}],
invalidComponentTracker: tracker}" /><br /><br />
<a class="oj-button-primary oj-button-xl"
href="http://localhost:8383/Test/index.html?root=home" id="create" type="button"
data-bind="ojComponent: {component: 'ojButton',
label: 'Login',
disabled: shouldDisableCreate()},
click: onClick"></a>
</div>
JAVASCRIPT CODE
define(['ojs/ojcore', 'knockout', 'ojs/ojinputtext', 'ojs/ojbutton', 'ojs/ojknockout-validation', 'ojs/ojmodel'
], function (oj, ko) {
/**
* The view model for the main content view template
*/
function logintestContentViewModel() {
var self = this;
self.tracker = ko.observable();
self.username = ko.observable("");
self.password = ko.observable("");
self.clickedButton = ko.observable();
self.buttonClick = function(data, event)
{
var trackerObj = ko.utils.unwrapObservable(self.tracker);
if (!this._showComponentValidationErrors(trackerObj))
{
return;
}
};
self.routePage = function(data,event)
{
self.clickedButton(event.currentTarget.id);
return true;
};
self.onClick = function()
{
self.buttonClick();
self.routePage();
}
self.shouldDisableCreate = function()
{
var trackerObj = ko.utils.unwrapObservable(self.tracker),
hasInvalidComponents = trackerObj ? trackerObj["invalidShown"] : false;
return hasInvalidComponents;
};
self._showComponentValidationErrors = function (trackerObj)
{
trackerObj.showMessages();
if (trackerObj.focusOnFirstInvalid())
return false;
};
}
return logintestContentViewModel;
});
If you are using ojRouter, then you can simply use
oj.Router.go("route name");
If you're not using ojRouter, then you can use the location object. Something like:
window.location.pathname='/homepage'
I recommend using ojRouter and it's canEnter() method for things like this.
Router cookbook demo:
http://www.oracle.com/webfolder/technetwork/jet/jetCookbook.html?component=router&demo=simple
JSDocs for Router canEnter method
http://www.oracle.com/webfolder/technetwork/jet/jsdocs/oj.RouterState.html
You can use
oj.Router.rootInstance.go('homepage');

Put two JavaScript functions together for one button? (JavaScript/HTML)

I have 2 separate functions working that use 2 different buttons, however I want to put them together for so that both functions are triggered simultaneously under one button.
I have a user registration form, and I have one function that sends the data into the database, and the other function checks if the username is existing or not.
What I need is for when the user submits the form, the form should not be submitted if the username already exists, thus an alert should appear saying for example "username taken, please try another". Nevertheless, if username has not been taken, then submit the form.
Can someone shed some light on how I can go about this and put both these functions together for the same button?
Register Function -
function registerUser() {
var Username = document.getElementById("txtusername").value;
var Firstname = document.getElementById("txtfirstname").value;
var Lastname = document.getElementById("txtlastname").value;
var Email = document.getElementById("txtemail").value;
var Password = document.getElementById("txtpassword").value;
var Confirmpass = document.getElementById("passwordconfirm").value;
db = window.openDatabase("SoccerEarth", "2.0", "SoccerEarthDB", 2*1024*1024);
db.transaction(function(tx) {
NewUser(tx, Username, Firstname, Lastname, Email, Password, Confirmpass);
}, errorRegistration, successRegistration);
}
function NewUser(tx, Username, Firstname, Lastname, Email, Password, Confirmpass) {
var _Query = ("INSERT INTO SoccerEarth(UserName, FirstName, LastName, Email, Password, CPass) values ('"+ Username +"','"+ Firstname +"','"+ Lastname +"','"+ Email +"', '"+ Password +"', '"+ Confirmpass +"')");
alert(_Query);
tx.executeSql(_Query);
}
function errorRegistration(error) {
navigator.notification.alert(error, null, "Got an error mate", "cool");
}
function successRegistration() {
navigator.notification.alert("User data has been registered", null, "Information", "ok");
$( ":mobile-pagecontainer" ).pagecontainer( "change", "#page4" );
}
Check username in database function-
function CheckUser()
{
db = window.openDatabase("SoccerEarth", "2.0", "SoccerEarthDB", 2*1024*1024);
db.transaction(UserDB, errorCB);
}
function UserDB(tx)
{
alert("user check");
var User = document.getElementById("txtusername").value;
tx.executeSql("SELECT * FROM SoccerEarth WHERE UserName='" + User + "'", [], renderUser);
}
function renderUser(tx,results) {
if (results.rows.length > 0) {
navigator.notification.alert("Username is taken, please try again.");
}
else
{
navigator.notification.alert("Username available!");
}
HTML -
<form id="form1" data-ajax="false">
<div data-role="fieldcontainer">
<label for="txtusername" data-theme="d">Username:</label>
<input type="text" id="txtusername" name="txtusername" maxlength="12" placeholder="Enter Username"/>
</div>
<div data-role="fieldcontainer">
<label for="txtfirstname" data-theme="d">First Name:</label>
<input type="text" id="txtfirstname" name="txtfirstname" placeholder="Enter First Name"/>
</div>
<div data-role="fieldcontainer">
<label for="txtlastname" data-theme="d">Last Name:</label>
<input type="text" id="txtlastname" name="txtlastname" placeholder="Enter Last Name"/>
</div>
<div data-role="fieldcontainer">
<label for="txtemail" data-theme="d">Email:</label>
<input type="email" id="txtemail" name="txtemail" placeholder="Enter Enter Email"/>
</div>
<div data-role="fieldcontainer">
<label for="txtpassword" data-theme="d">Password:</label>
<input type="text" id="txtpassword" name="txtpassword" maxlength="12" placeholder="Enter Password"/>
</div>
<div data-role="fieldcontainer">
<label for="passwordconfirm" data-theme="d">Confirm Password:</label>
<input type="text" id="passwordconfirm" name="passwordconfirm" maxlength="12" placeholder="Confirm password"/>
</div>
<br>
<input type="submit" value="Register User">
Input Validations (JQUERY) -
$('#form1').submit(function (e) {
e.preventDefault();
}).validate({
rules: {
txtusername: {
required: true
},
txtfirstname: {
required: true
},
txtemail: {
required: true
},
txtpassword: {
required: true
},
passwordconfirm: {
required: true
}
},
messages: {
txtusername: {
required: "Please enter your Username."
},
txtfirstname: {
required: "Please enter your First Name."
},
txtemail: {
required: "Please enter your Email."
},
txtpassword: {
required: "Please enter your Password."
},
passwordconfirm: {
required: "Please enter your password again."
}
},
errorPlacement: function (error, element) {
error.appendTo(element.parent().prev());
},
submitHandler: function (form, user) {
registerUser(form);
return false;
}
});
I can see in your code that you check if the username is available, so you can use the event onchange
<input type="text" onchange="CheckUser()" id="txtusername" name="txtusername" maxlength="12" placeholder="Enter Username"/>
so when the user write some your function CheckUser() is activated, after that you can use normally , inside of
if (results.rows.length > 0) {
navigator.notification.alert("Username is taken, please try again.");
} else {
//add event click only if is available your username
navigator.notification.alert("Username available!");
element = document.getElementById("btnSend");
element.addEventListener("click", registerUser())
}
and write your input submit with this id btnSend
<input id="btnSend" type="submit" value="Register User">
So in this way you validate if the username is available only in this case you add RegisterUser() for your submit
last but not least be more careful because you wrote code in your JS (Query for DB) and this can be affecty your security
Create new function which call this 2 functions
function newfunction()
{
// you need to return true/false from check user function
if(CheckUser())
{
registerUser();
}
}
and call this on onclick
<input type="submit" value="Register User" onclick="newfunction()">
Use a onsubmit event to handle the registration
<form id="form1" data-ajax="false" onsubmit="doSubmit();">
and javascript function will look like
function doSubmit(){
// check if the user exists. Return a boolean value to return the status
var userExists = checkUser();
// if user exists, return false to protect form from submitting.
if(userExists){
return false;
}
// if user does not exists, register the user
registerUser();
}

Comparing value from input with backbone collection data

I'm trying to create very simple login with backbonejs. Collection stores usernames and passwords. Login view has two inputs and on click it should perform check function and compare input value with data from collection.
Html part looks like this:
<div class="login-block">
<script type="text/template" id="start">
<form id="login">
<div class="input-wrapper"><input type="text" placeholder="Username" id="username" required></div>
<div class="input-wrapper"><input type="password" placeholder="Password" id="password" required></div>
<div class="input-wrapper"><button class="btn">Sign in!</button></div>
</form>
</script>
<div class="error" class="block">
Error
</div>
<div class="success">
Success
</div>
</div>
Here is my Js code:
var User = Backbone.Model.extend({
defaults: {
login: 'root',
mail: 'root#mail.com',
password: ''
}
});
var user = new User();
//variable to store username
var loginData = {
username: "",
password: ""
}
// userbase
var UserCollection = Backbone.Collection.extend({
model: User
});
var userCollection = new UserCollection([
{
username: 'Ivan',
mail: 'ivan#mail.com',
password: '1234'
},
{
username: 'test',
mail: 'test#mail.com',
password: 'test'
}
]);
// login page
var LoginView = Backbone.View.extend({
el: $(".login-block"),
events: {
"click .btn": "check"
},
check: function(){
loginData.username = this.$el.find("#username").val(); // store username
loginData.password = this.$el.find("#password").val();// store password
if (loginData.username === userCollection.each.get("username") && loginData.password === userCollection.each.get("password"))
{appRouter.navigate("success", {trigger: true});
}else{
appRouter.navigate("error", {trigger: true});
}
},
render: function () {
//$(this.el).html(this.template());
var template = _.template($('#start').html())
$(this.el).html(template());
//template: template('start');
return this;
}
});
var loginView = new LoginView({collection: userCollection});
var AppRouter = Backbone.Router.extend({
routes: {
'': 'index', // start page
'/error': 'error',
'/success': 'success'
},
index: function() {
loginView.render();
console.log("index loaded");
},
error: function(){
alert ('error');
},
success: function(){
console.log('success');
}
});
var appRouter = new AppRouter();
Backbone.history.start();
It works fine to the check function, and it stores username and password, but something is clearly wrong either with router or check function when it starts comparison. Instead of routing to success or error page, it rerenders index page.
P.S I didn't use namespacing and code in general is not of a greatest quality, but it was made for educational purpose only.
You have to add the attribute type="button" to your button, otherwise it will submit the form when clicked (See this question):
<script type="text/template" id="start">
<form id="login">
<div class="input-wrapper"><input type="text" placeholder="Username" id="username" required></div>
<div class="input-wrapper"><input type="password" placeholder="Password" id="password" required></div>
<div class="input-wrapper"><button class="btn" type="button">Sign in!</button></div>
</form>
</script>
You can also return false in the click event handler, which would cancel the default action. (submitting the form, if you don't add type="button").
For comparing the values with the hardcoded collection, you can't call each as you where doing (which is an iteration function provided by Underscore) because you would receive an error. You could use Underscore's findWhere method which is also available in Backbone collections. So the click event handler (Your check function) could look like this:
check: function(){
loginData.username = this.$el.find("#username").val(); // store username
loginData.password = this.$el.find("#password").val();// store password
if(userCollection.findWhere({username: loginData.username, password: loginData.password})){
appRouter.navigate("success", {trigger: true});
}else{
appRouter.navigate("error", {trigger: true});
}
return false;
},
You can try it on this fiddle
The logic check you're doing doesn't look like it would work to me. I would expect the following to generate an error:
userCollection.each.get('username')
the function you're calling on your collection, each, is a wrapped underscore method which takes a function callback as a parameter. If you want to check your username and password, I'd do something like this:
var user = userCollection.findWhere({ username: loginData.userName });
This will return you the model where the username matches. Then you can check the password of that model:
if (user.get('password') === loginData.password) {
// do something
} else {
// do something else
}
EDIT Heck, you can do both checks at once:
var user = userCollection.findWhere({ username: loginData.userName, password: loginData.password });
I'll leave the previous code up just to demonstrate.

Backbone Login Screen

I am fairly new to BackboneJS. After writing multiple GET implementation, I am trying to implement Login screen with Backbone JS.
Folder Structure
app
-->model
-->view
-->templates
-->server
formSignIn.html
<form class="form-signin" role="form">
<h2 class="form-signin-heading">Please sign in</h2>
<input type="email" id="email" class="form-control" placeholder="Email address" required="" autofocus="">
<input type="password" id="password" class="form-control" placeholder="Password" required="">
<label class="checkbox">
<input type="checkbox" value="remember-me"> Remember me
</label>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
Backbone View
var SignInView = Backbone.View.extend({
el:$('.container'),
template:_.template('../templates/formSignIn.html'),
events: {
"click .btn":"signIn"
},
initialize: function() {
this.model.on('change', this.render, this);
},
render: function() {
var attributes = this.model.toJSON();
this.$el.html(this.template(attributes));
},
signIn: function() {
this.model.signIn({
email: $('#email').val(),
password: $('#password').val()
});
}
});
var signInView = new SignInView({model: signInModel});
signInView.render();
Backbone Model
var SignInModel = Backbone.Model.extend({
url:function() {
'http://localhost:3000/singIn'
},
defaults: {
email:"",
password:""
},
parse: function(resp) {
return resp;
},
signIn: function() {
this.save();
}
});
var signInModel = new SignInModel();
Issues:
Template HTML is not rendering. When I open the page it shows ../templates/formSignIn.html. It means _template is not recognizing the html.
How is the view and model implementation? Is this the right way of doing? I am not very confident about calling the model's save().
In answer to your first question _.template(...) takes in a string. If you want the contents of ../templates/formSignIn.html you must include it in the dom or request it, for example using ajax.
If included in the dom it would look something it like this:
// Somewhere in the html...
<script type="text/html" id="form-signin-tpl">
<form class="form-signin" role="form">
...
</form>
</script>
// in your view
_.template($('#form-signin-tpl').html());
If you need to request the template during runtime you can use RequireJS which handles this nicely, or you could manually request it with jQuery, perhaps like this:
$.get( "path/to/templates/formSignIn.html", function( html ) {
var tpl = _.template(html);
});
In answer to the second question
the model's url parameter is a string, not a function.
You only need to define parse if you need to customize how the server's data is parsed.
This is probably more what you're going for:
var SignInModel = Backbone.Model.extend({
url: 'http://localhost:3000/singIn',
defaults: {
email:"",
password:""
},
signIn: function() {
this.save();
}
});
var signInModel = new SignInModel();
Lastly, regarding authenticating a user, a model might not be the best way to handle this. There are a few SO questions regarding athenticating a user in Backbone apps, such as this one

Categories

Resources