I have a html with this template:
<template name="entryfield">
<input type="text" id="name" placeholder="Name" /> <input type="text" id="message" placeholder="Your Message" /><br>
<input type="button" class="plusbutt" value="+"/><input type="button" class="minusbutt" value="-"/>
</template>
and I want to declare the 2 buttons event:
Template.entryfield.events = {
'click .plusbutt': function() {
// Submit the form
var name = document.getElementById('name');
var mood = document.getElementById('mood');
var message = document.getElementById('message');
if(name.value != '' && message.value != ''){
Messages.insert({
name: name.value,
mood: '+',
message: message.value,
time: Date.now()
});
name.value = '';
message.value = '';
}
}
}
'click .minusbutt': function() {
// Submit the form
var name = document.getElementById('name');
var mood = document.getElementById('mood');
var message = document.getElementById('message');
if(name.value != '' && message.value != ''){
Messages.insert({
name: name.value,
mood: '-',
message: message.value,
time: Date.now()
});
name.value = '';
message.value = '';
}
}
But I have error:
chat.js:58:19: Unexpected token :
Which line 58 is the beginning of the second event declaration. But when I totally take out second event, everything just work. My question is how do people declare more than 1 function in the same template events? I seen it everywhere but I just cannot get this to work. Thanks!
Where can I find reference on the template event? The problem on learning Meteor is their functions is from all over, some from MongoDB, Some from Handlebar, and Some from JavaScripts, which make it rather hard to pick up for beginner.
Your events declaration syntax is wrong, be careful !
Be sure to check the Meteor docs, everything is detailed : http://docs.meteor.com/#template_events
It should be like this :
Template.entryfield.events({
"click .plusbutt":function(){
/* ... */
},
"click .minusbutt":function(){
/* ... */
}
});
Template.myTemplate.events is a function which takes an object as parameter.
Each members of the object should be a key/value pair, the key being the event declaration and the value the corresponding handler.
Related
I am trying to properly validate form-data on my backend and still be able to have a nice user experience with form validation on my front end which is written in Javascript. I have all the form validation done on the front end, in order to get the effect we want we used e.PreventDefault() on our submit button so we can display any input errors to the user without a reload. The issue is when you actually fill out the form now and click submit there is no POST request being sent to the server because of the preventDefault.
Removing the line completely seemed to fix the problem of our server not receiving post requests but that creates the issue of the front end form validation being completely pointless because the error messages aren't displayed because of the refreshed page.
Javascript Front End Validation:
let btn = document.querySelector('.btn')
btn.addEventListener('click', function(e) {
e.preventDefault() // <---- THIS IS THE ISSUE
let firstName = document.querySelector('.firstName').value
let lastName = document.querySelector('.lastName').value
let email = document.querySelector('.email').value
let createPassword = document.querySelector('.createPassword').value
let verifyPassword = document.querySelector('.verifyPassword').value
let firstNameSubmit = false
let lasttNameSubmit = false
let emailSubmit = false
let createPasswordSubmit = false
let verifyPasswordSubmit = false
if (/^\s+$/.test(firstName) || firstName == null || firstName == '') {
document.querySelector('.firstNameError').innerHTML = 'First Name is a required field'
document.querySelector('.firstName').style.borderBottom = '1px solid red'
} else if (!/^\s+$/.test(firstName) || firstName !== null || firstName !== '') {
document.querySelector('.firstNameError').innerHTML = null
document.querySelector('.firstName').style.borderBottom = '1px solid #2ecc71'
firstNameSubmit = true
} if (/^\s+$/.test(lastName) || lastName == null || lastName == '') {
document.querySelector('.lastNameError').innerHTML = 'Last Name is a required field'
document.querySelector('.lastName').style.borderBottom = '1px solid red'
} else if (!/^\s+$/.test(lastName) || lastName !== null || lastName !== '') {
document.querySelector('.lastNameError').innerHTML = null
document.querySelector('.lastName').style.borderBottom = '1px solid #2ecc71'
lasttNameSubmit = true
} if (!/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)) {
document.querySelector('.emailError').innerHTML = 'Please enter a valid email'
document.querySelector('.email').style.borderBottom = '1px solid red'
} else if (/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)) {
document.querySelector('.emailError').innerHTML = null
document.querySelector('.email').style.borderBottom = '1px solid #2ecc71'
emailSubmit = true
} if (/^\s+$/.test(createPassword) || createPassword == null || createPassword == '' || createPassword.length < 6) {
document.querySelector('.createPasswordError').innerHTML = 'Password must be longer than 6 characters'
document.querySelector('.createPassword').style.borderBottom = '1px solid red'
} else if (!/^\s+$/.test(createPassword) || createPassword !== null || createPassword !== '' || createPassword.length >= 6) {
document.querySelector('.createPasswordError').innerHTML = null
document.querySelector('.createPassword').style.borderBottom = '1px solid #2ecc71'
createPasswordSubmit = true
} if (!createPasswordSubmit) {
document.querySelector('.verifyPasswordError').innerHTML = `Passwords don't match`
document.querySelector('.verifyPassword').style.borderBottom = '1px solid red'
} else if (verifyPassword == createPassword){
document.querySelector('.verifyPasswordError').innerHTML = null
document.querySelector('.verifyPassword').style.borderBottom = '1px solid #2ecc71'
verifyPasswordSubmit = true
}
Go Backend Halders:
http.HandleFunc("/signup", signupHandler) // inside func main()
func signupHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
tpl.ExecuteTemplate(w, "signup.html", nil)
fmt.Printf("METHOD: %s | URL: %v\n", r.Method, r.URL)
return
}
fmt.Printf("METHOD: %s | URL: %v\n", r.Method, r.URL)
r.ParseForm()
f := r.PostFormValue("fname")
l := r.PostFormValue("lname")
e := r.PostFormValue("email")
pw := r.PostFormValue("pass")
hash, err := helper.HashPassword(pw)
if err != nil {
fmt.Printf("Hashing Error")
}
fmt.Println("LoginValues")
fmt.Printf("%s\n, %s\n, %s\n, %s\n", f, l, e, hash)
}
Signup Template HTML:
<form action="/signup" method="post">
<h3>First Name</h3>
<input name="fname" type="text" class="firstName">
<p class="firstNameError"></p>
<h3>Last Name</h3>
<input name="lname" type="text" class="lastName">
<p class="lastNameError"></p>
<h3>Email</h3>
<input name="email" type="text" class="email">
<p class="emailError"></p>
<h3>Create Password</h3>
<input name="pass" type="password" class="createPassword">
<p class="createPasswordError"></p>
<h3>Verify Password</h3>
<input type="password" class="verifyPassword">
<p class="verifyPasswordError"></p>
<button class="btn" type="submit">Register</button>
</form>
I just want to know if there's a work around for front end with back end form validation either with preventDefault or if I need to approach the concept a different way if so how? Thanks in advance!
Because it's a type="submit" button, event.preventDefault() is preventing the "submit" event from firing (and the "submit" event is what sends the data to the backend).
Instead of listening for a "click" event on the button, I think it is better listen to a "submit" event on the form. It will be triggered on the form when you click a button with type="submit."
The form will now be the event's target.
let form = document.getElementById('my-form')
form.addEventListener('submit', function(event) {})
So, at the beginning of your function, you should be able to prevent the submit action by calling
event.preventDefault();
But, you can also store the form to a local variable, since that is the element that the submit event is triggering on:
let form = event.target
Then, if there are no errors, you can trigger the submit on the form at the end of your function:
form.submit()
all together:
let form = document.getElementById('my-form')
form.addEventListener('submit', function(event) {
event.preventDefault()
let form = event.target
let errors = false;
//do all of the error checking here, if there's an error, set errors to true
if(!errors) {
form.submit()
}
})
(There might be a better way, but that's what I could think of off the top of my head. Also, it might be easier to get all of the data values by adding a "name" attribute to each input, instead of querying each field).
I fixed the issue by messing around with #Maiya had provided. I took a step back and re-evaluated the javascript and what exactly was going on. Used a submit even listener and had basic form validation on the front end and now I can just ensure on the backend. I ended up using the e.preventDefault() right after I stored the form instance in a variable and then checked and submitted or it just shows the errors.
Javascript Changes:
let submit = document.getElementById("signupForm")
submit.addEventListener("submit", function(e){
let form = e.target // get form instance
e.preventDefault()
console.log(form)
// error handling
if (firstNameSubmit == false || lasttNameSubmit == false || emailSubmit == false || createPasswordSubmit == false || verifyPasswordSubmit == false) {
console.log('form not done')
} else { // form completed send to backend!
form.submit()
}
SignupHandler Changes:
user := &User{
fname: r.PostFormValue("fname"),
lname: r.PostFormValue("lname"),
email: r.PostFormValue("email"),
pw: r.PostFormValue("pass"),
}
user.hash = string(helper.HashPassword(user.pw))
//begin server validation
if user.fname == "" {
http.Redirect(w, r, "/signup", http.StatusBadRequest)
tpl.ExecuteTemplate(w, "signup.html", nil)
} else {
http.Redirect(w, r, "/login", http.StatusOK)
}
Instead of using Form method='post'(i.e., instead of using form to make post requests) just make a post request using axios. In that way it works even if there is event.preventDefault()
I have been trying to use JS OOP to do form validation; I tested the code in Firefox and chrome :both browsers were just frozen. they did not submit regardless of whether or not the inputs matched the prescribed regular expression. So, who knows where I got it wrong? Pls: I know jQuery validator exists and I can also use plain JS to go as far as circumstances permit. Here, my interest is connecting JS OOP to the DOM. Blogs and textbooks I have read so far have not really shown me how to connect jS OOP to DOM scripting.So, I am just scavenging through rubble, looking for my way out.This code has taken a toll on my battery so I decided to share it here.
<form method = 'post' action ='somewhere.com' onsubmit = 'return formApp.validateInputs.apply(formApp);'>
<p>
Name: <input type = 'text' name = 'userName' id = 'userName'>
</p>
<p>
Phone: <input type = 'text' name = 'userPhone' id = 'userPhone'>
</p>
<input type = 'submit' id = 'sub' value = 'Submit Data'>
</form>
var formApp = {
userNameReg: /[a-z0-9 ' _ ]+/gi,
onlySpaceReg: /\s+/,
phoneReg: /\d{3}/,
userName: document.getElementById('userName').value,
userPhone: document.getElementById('userPhone').value,
error: [],
reportError: function () {
for (var i = 0; i < this.error.length; i++) {
alert(this.error[i] + '\n')
}
},
validateInputs: function () {
if (!this.userNameReg.test(this.userName) || this.onlySpaceReg.test(this.userName)) {
this.error.push['Name contains illegal character'];
return false
} // end name validation
if (!this.phoneReg.test(this.userPhone)) {
this.error.push['Only a three-digit number'];
return false;
} // end phone validation
if (this.error.length > 0) {
this.reportError();
return false;
}
return true;
} // end validateInputs
}; // end formApp obj
One of the problems is that you will never get an alert, because you return from the function in all the if blocks where you add an error. So the "this.reportError();" can never be executed. Remove the "return false" statements from ifs.
validateInputs: function () {
if (!this.userNameReg.test(this.userName) || this.onlySpaceReg.test(this.userName)) {
this.error.push['Name contains illegal character'];
}// end name validation
if (!this.phoneReg.test(this.userPhone)) {
this.error.push['Only a three-digit number'];
}// end phone validation
if (this.error.length > 0) {
this.reportError();
return false;
}
return true;
}
I am facing an issue with using ng-init and assign it model inside my html.
The following code works fine. The following code is for Add/Edit functionality. For example, when row is is opened in Edit mode than it persist existing value and shows it in textbox.
<div>
<div ng-if="title == 'Add Student'">
<input type="text" name="name"placeholder="Student Name" data-ng-model="registration.Student.FirstName" maxlength="50">
</div>
<div ng-if="title == 'Edit Student'">
<input type="text" name="name"placeholder="Student Name" data-ng-model="student.Student.FirstName" maxlength="50">
</div>
</div>
However, the following code which is short version of above code does not work. I mean when the row is opened in edit mode it shows text field but does not show existing value (first name) in it. Why?
<div ng-init="model = (title == 'Add Student' ? registration.Student : student.Student)">
<input type="text" name="name" placeholder="Student Name" data-ng-model="model.FirstName" maxlength="50">
</div>
Please suggest whether ng-init can't be used in this way or some issue in my code?
thanks
Controller
var currentState = $state.current.name;
if if (currentState == "Add")
{
$scope.registration = {
Student: {
FirstName: '',
}
var _init = function () {
}
$scope.title = " Add Student";
}
else
{
$scope.student= {};
$scope.student= response[0];
var _init = function () {
$scope.title = " Edit Student";
}
}
You are ng-init block is wrong currently it is returning true or false, you are messing with brackets.
Markup
<div ng-init="model = (title == 'Add Student') ? registration.Student : student.Student">
<input type="text" name="name" placeholder="Student Name" data-ng-model="model.FirstName" maxlength="50">
</div>
Update
In your current case you ng-init is getting executed while element rendered on the DOM, at that instance on time registration.Student & student.Student doesn't have any value. Evaluation of ng-init setting null object to the model student. I'd suggest you do set model value from the controller logic that would be more safer.
Code
var currentState = $state.current.name;
if (currentState == "Add")
{
$scope.registration = {
Student: {
FirstName: '',
}
var _init = function () {
}
$scope.title = " Add Student";
}
else
{
$scope.student= {};
$scope.student= response[0];
var _init = function () {
$scope.title = " Edit Student";
}
//shifted logic in controller
$scope.model = (title == 'Add Student' ? registration.Student : student.Student);
}
Markup
<div>
<input type="text" name="name" placeholder="Student Name"
data-ng-model="model.FirstName" maxlength="50"/>
</div>
Other way you could add one more flag like loadedData which will says that ajax response has been fetched & registration.Student & student.Student values are available in the scope.
Markup
<div ng-if="loadedData">
<input type="text" name="name" placeholder="Student Name" data-ng-model="model.FirstName" maxlength="50">
</div>
Code
var currentState = $state.current.name;
if (currentState == "Add")
{
$scope.registration = {
Student: {
FirstName: '',
}
var _init = function () {
}
$scope.title = " Add Student";
}
else
{
$scope.student= {};
$scope.student= response[0];
var _init = function () {
$scope.title = " Edit Student";
}
//set flag
$scope.loadedData = true;
}
I'm working on some JavaScript validation and need a way to print out error messages.
I have an array called errorList and I have a div which I would like to print the array contents out into, called divErrorList.
I have a function which adds the error to the array:
errorList[errorList.length] = errorArray;
So now I want to print errorList out, perhaps using innerHTML ?
Although I have tried this, and I don't get an error but I do not see the error list being printed either.
document.getElementById("divErrorList").innerHTML+=(errorList[i]);
Since you don't want to post your essential code, I'm going to assume errorArray is... an array?
So errorList would be an array of arrays? Then you need a nested loop, or to join each error like so:
var errorList = [
['error 1.1', 'error 1.2'],
['error 2.1'],
['error 3.1', 'error 3.2', 'error 3.3'],
['error 4.1', 'error 4.2']
];
var errorString = "";
// for each errorArray
for(var i=0, len=errorList.length; i<len; i++){
// join the errorArray
errorString += '<h1>ErrorArray #'+ i +'</h1>'
+'<ul><li>'+ errorList[i].join('</li><li>') +'</li></ul>';
}
document.body.innerHTML = errorString;
JS Fiddle Demo
A simple way to populate an array with errors is the following:
Assign to your elements a data-validate and a data-error attribute:
<form name="myForm">
* Name
<input name=Name data-validate=text data-error="Name cannot be empty"> <br>
* Email
<input name=Email data-validate=email data-error="Invalid Email"> <br>
* Message
<textarea name=Message data-validate=text data-error="Enter a Message">
</textarea> <br>
<input type="submit">
</form>
<div id="divErrorList"></div>
Than cache your selectors:
var myForm = document.forms.myForm;
var divError = document.getElementById("divErrorList");
than create an Object that will contain all the needed validate methods:
var validator = {
text : function(val) { return !/^\s*\S+.*/.test(val); },
email : function(val) { return !/\S+#\S+\.\S+/.test(val); }
};
(You can additionally improve the regexes above)
Once you submit your Form, you check all your Form Elements with this.elements and after you make sure one has a data-validate, you simply call your respective validate method for that field Value.
If your validate method returns true means that a certain field did not passed the test, so you can move on and .push() into an errors Array the message stored in that element's data-error attribute:
function validateForm(event) {
var errors = [];
var el = this.elements;
for(var i=0; i<el.length; i++){
var data = el[i].dataset;
var validateType = data.validate;
var validateError = data.error;
if(validateType){ // "text", "email", ...
if(validator[validateType](el[i].value)) errors.push( validateError );
}
}
// Check for errors length and write to DIV...*
}
myForm.onsubmit = validateForm;
(*)Than, (always inside the same function) you simply check for the errors Array length and if there's some errors you can write your errors to your element by joining the Array keys with <br> (for example)
if(errors.length){
event.preventDefault();
divError.innerHTML = errors.join("<br>");
}
var myForm = document.forms.myForm;
var divError = document.getElementById("divErrorList");
var validator = {
text : function(val) { return !/^\s*\S+.*/.test(val); },
email : function(val) { return !/\S+#\S+\.\S+/.test(val); }
};
function validateForm(event) {
var errors = [];
var el = this.elements;
for(var i=0; i<el.length; i++){
var data = el[i].dataset;
var validateType = data.validate;
var validateError = data.error;
if(validateType){ // "text", "email", ...
if(validator[validateType](el[i].value)) errors.push( validateError );
}
}
if(errors.length){
event.preventDefault();
divError.innerHTML = errors.join("<br>");
}
}
myForm.onsubmit = validateForm;
<form name="myForm">
* Name
<input name=Name data-validate=text data-error="Name cannot be empty"> <br>
* Email
<input name=Email data-validate=email data-error="Invalid Email"> <br>
* Message
<textarea name=Message data-validate=text data-error="Enter a Message">
</textarea> <br>
<input type="submit">
</form>
<div id="divErrorList"></div>
html:
username: <input type="text" ng-model="username" /><br />
password: <input type="text" ng-model="password" /><br />
<button class="btn btn-primary" type="button" ng-click="login()">Login</button>
js:
$scope.login = function(){
var user = $scope.username;
var pass = $scope.password;
if(user != undefined && pass != undefined){
alert("NOT BLANK" + " user: " + user + " pass: " + pass);
} else {
alert("BLANK");
}
};
Question:
When I click Login for the first time with input values from the 2 fields, alert is showing NOT BLANK user: test pass: value, but when I remove the values from the fields and click Login, alert shows NOT BLANK user: pass: which is not correct since the fields values have been removed. If I refresh the page, and click Login, alert will show BLANK. I think it is issue with cache. can someone help. I am novice with angularjs
This is not a Cache Issue. By checking with != undefined all you do is check if the String or Variable was defined - but it still can be an empty String.
So basically what happens is: you enter something, and the two Strings for user and pass get initialized. From this time, a check for undefined will always return false.
When you remove all letters, the two Variables still contain a String-Object, just without characters (basically like this: var user = '').
Change your code to the following, that should work:
$scope.login = function(){
var user = $scope.username;
var pass = $scope.password;
if(!user && !pass){
alert("BLANK");
} else {
alert("NOT BLANK" + " user: " + user + " pass: " + pass);
}
};
The checks user != undefined && pass != undefined) are too stringent.
You should check for empty strings: user === '' && pass === ''.
Update:
Initialize the values such that they are initially not undefined either:
var user = $scope.username || '';
var pass = $scope.password || '';