Aurelia: Trigger Validation on tab-out(blur event) - javascript

I have returned a validation group to validate my inputs which triggers on submit button and I want to trigger by validation on blur event to trigger respective validation, not all.
For example:
HTML:
<form role="form" submit.delegate="welcome()" validate.bind="validation">
<div class="form-group">
<label for="fn">First Name</label>
<input type="text" value.bind="firstName & updateTrigger:'blur'" class="form-control" id="fn" placeholder="first name" />
<span>${firstName}</span>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
Validation Rule in ViewModel:
this.validation = validation.on(this)
.ensure('firstName')
.isNotEmpty()
.hasMinLength(3)
.hasMaxLength(10);
Since I have written updateTrigger:'blur' none of the validation are getting triggered.
Once you remove updateTrigger:'blur' all the validations are working expected.
Requirement:
I want that once the input box loses focus(blur is triggered) then validation(s) related to 'firstname' are triggered no other validation(of other properties).
Thanks in advance.

This is now supported in the aurelia-validation alpha. Check out this blog post: https://www.danyow.net/aurelia-validation-alpha/
Here's an example: https://gist.run?id=381fdb1a4b0865a4c25026187db865ce
registration-form.html
<template>
<require from="./validation-summary.html"></require>
<h1>Register!</h1>
<form submit.delegate="submit()"
validation-renderer="bootstrap-form"
validation-errors.bind="errors">
<validation-summary errors.bind="errors"
autofocus.bind="controller.validateTrigger === 'manual'">
</validation-summary>
<div class="form-group">
<label class="control-label" for="first">First Name</label>
<input type="text" class="form-control" id="first" placeholder="First Name"
value.bind="firstName & validate">
</div>
<div class="form-group">
<label class="control-label" for="last">Last Name</label>
<input type="text" class="form-control" id="last" placeholder="Last Name"
value.bind="lastName & validate">
</div>
<div class="form-group">
<label class="control-label" for="email">Email</label>
<input type="email" class="form-control" id="email" placeholder="Email"
value.bind="email & validate">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<button type="button" class="btn btn-default" click.delegate="reset()">Reset</button>
</form>
</template>
registration-form.js
import {inject, NewInstance} from 'aurelia-dependency-injection';
import {ValidationController, validateTrigger} from 'aurelia-validation';
import {required, email, ValidationRules} from 'aurelia-validatejs';
#inject(NewInstance.of(ValidationController))
export class RegistrationForm {
#required
firstName = '';
#required
lastName = '';
#required
#email
email = '';
constructor(controller) {
this.controller = controller;
// the default mode is validateTrigger.blur but
// you can change it:
// controller.validateTrigger = validateTrigger.manual;
// controller.validateTrigger = validateTrigger.change;
}
submit() {
let errors = this.controller.validate();
// todo: call server...
}
reset() {
this.firstName = '';
this.lastName = '';
this.email = '';
this.controller.reset();
}
}

Aurelia's validation was updated in late 2016 to include a changeOrBlur validateTrigger option, which in my opinion should be the new default. Here's how to use it:
constructor(controller) {
this.controller = controller;
controller.validateTrigger = validateTrigger.changeOrBlur;
// controller.validateTrigger = validateTrigger.blur; (default)
// controller.validateTrigger = validateTrigger.change;
// controller.validateTrigger = validateTrigger.changeOrBlur;
// controller.validateTrigger = validateTrigger.manual;
}

Related

How do I group inputs in Local storage to be one "Event" categorized by my Date time input

In my app I collect information from the user and store it in Local storage using javascript like this.
Event Name (1 to 20 characters):
<input type="text" id="eventname" name="eventname" required
minlength="1" maxlength="20" size="20">
<label for="datetime">Event Date and Time:</label>
<input type="datetime-local" id="date" name="date" required
minlength="1" maxlength="20" size="20">
<label for="eventlocation">Event Location (1 to 20 characters):</label>
<input type="text" id="location" name="location" required
minlength="1" maxlength="20" size="20">
<label for="notes">Notes (0 to 50 characters): </label>
<input type="text" id="notes" name="notes" required
minlength="0" maxlength="50" size="50">
<script src="app.js"></script>
I then have an app.js document which puts it into local storage
const locationTxt = document.querySelector('#location');
locationTxt.addEventListener('change', (event) => {
localStorage.setItem('location', event.target.value);
function getSavedData() {
console.log('location', localStorage.getItem('location'));
(except i have these fucntions for each of the inputs.)
How Would i go about taking all these inputs in locale storage and displaying it as 1 event that is able to be categorized by time?
One way would be to store event data in an object:
{
'01-02-1900': [
... // Array of events
],
'01-01-1900': [
... // Array of events
],
...
}
And then using JSON.parse and JSON.stringify to read/write to localStorage. 😊
For instance:
/**
* This override localStorage in Stack Snippet
*/
const customStorage = { data: {} };
customStorage.getItem = index => customStorage.data[index] || null;
customStorage.setItem = (index, payload) =>
(customStorage.data[index] = payload);
/**
* Replace customStorage with localStorage below.
*/
const inputs = document.querySelectorAll("input");
const storageIndex = "myTestStorage";
const storeInLocal = formData => {
const { date, event } = formData;
const toStore = JSON.parse(customStorage.getItem(storageIndex)) || {};
if (!toStore[date]) toStore[date] = [];
toStore[date].push(event);
customStorage.setItem(storageIndex, JSON.stringify(toStore));
};
const readForm = () => {
let values = {};
inputs.forEach(({ name, value }) => {
values[name] = value;
});
const { date, eventname, location, notes } = values;
return {
date,
event: {
eventname,
location,
notes
}
};
};
const outputStorage = () => {
const storage = customStorage.getItem(storageIndex) || "";
document.getElementById("output").innerText = storage;
};
document.getElementById("eventForm").addEventListener("submit", e => {
e.preventDefault();
const formData = readForm();
storeInLocal(formData);
outputStorage();
});
<!DOCTYPE html>
<html lang="en">
<head>
<title>Store form data in localStorage</title>
<link
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
rel="stylesheet"
/>
<style>
pre {
white-space: pre-wrap;
}
</style>
</head>
<body>
<main id="app" role="main" class="container">
<form id="eventForm">
<div class="form-group row">
<label for="eventname">Event Name</label>
<div class="col-sm-6">
<input
type="text"
id="eventname"
name="eventname"
required
minlength="1"
maxlength="20"
/>
</div>
</div>
<div class="form-group row">
<label for="datetime">Event Date and Time:</label>
<div class="col-sm-6">
<input
type="datetime-local"
id="date"
name="date"
required
minlength="1"
maxlength="20"
/>
</div>
</div>
<div class="form-group row">
<label for="eventlocation">Event Location</label>
<div class="col-sm-6">
<input
type="text"
id="location"
name="location"
required
minlength="1"
maxlength="20"
/>
</div>
</div>
<div class="form-group row">
<label for="notes">Notes</label>
<div class="col-sm-6">
<input
type="text"
id="notes"
name="notes"
required
minlength="0"
maxlength="50"
/>
</div>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
<h1 class="h4">Output</h1>
<p>Hit "save" multiple times, and change the date occasionally.
<p>
<pre id="output"></pre>
</p>
</main>
</body>
</html>

Trying to implement closure on event handler? Error: undefined

I have trying to get the values out of a form when the register button is clicked.
setupFormUI() and the relevant form fields are saved in variables
$($rego_form).on("submit", getRegistrationFormValue); is called - a handler should be able to have access to setupFormUI() variables (closure) but it seems to not do anything
ISSUE: getRegistrationFormValue doesn't log anything. I can make it work if I pass arguments to the function... but I want to use
closure
setupFormUI();
function setupFormUI() {
var $name = $("#name");
var $age = $("#age");
var $department = $("#department");
var $position = $("#position");
var $rego_form = $("#rego-form");
$($rego_form).on("submit", getRegistrationFormValue);
}
function getRegistrationFormValue() {
// alert("asdasd");
var name = $name.val();
var age = $age.val();
var department = $department.val();
var position = $position.val();
console.log("----->", name, age, position, department);
}
html
<form id="rego-form">
<div class="row">
<div class="col-md-5">
<div class="form-group">
<label>Company (disabled)</label>
<input type="text" class="form-control" disabled placeholder="Company" value="Creative Code Inc.">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label>name</label>
<input type="text" id="name" class="form-control" placeholder="name" value="michael">
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="exampleInputEmail1">Age</label>
<input id="age" class="form-control" placeholder="age">
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Department Name</label>
<input type="text" id="department" class="form-control" placeholder="department" value="Marketing">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label>Position</label>
<input type="text" id="position" class="form-control" placeholder="position" value="social media manager">
</div>
</div>
</div>
<button type="submit" id="rego-user-btn" class="btn btn-info btn-fill pull-right">Register</button>
<div class="clearfix"></div>
</form>
You need the variables to be in scope, you can use an anonymous closure as a callback to achieve this.
setupFormUI();
function setupFormUI() {
var $name = $("#name");
var $age = $("#age");
var $department = $("#department");
var $position = $("#position");
var $rego_form = $("#rego-form");
$rego_form.on("submit", function(){
var name = $name.val();
var age = $age.val();
var department = $department.val();
var position = $position.val();
console.log("----->", name, age, position, department);
});
}
An alternative to the accepted answer — give the "handler" a meaningful context of this with Function.prototype.bind(), or maybe just use the ES6 class.
setupFormUI();
function setupFormUI() {
var args = {
$name: $("#name"),
$age: $("#age"),
$department: $("#department"),
$position: $("#position"),
$rego_form: $("#rego-form")
}
args.$rego_form.submit(getRegistrationFormValue.bind(args));
}
function getRegistrationFormValue(e) {
var name = this.$name.val();
var age = this.$age.val();
var department = this.$department.val();
var position = this.$position.val();
console.log("----->", name, age, position, department);
e.preventDefault();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="rego-form" action="#">
<input id="name" value="John Doe" />
<input id="age" value="37" />
<input id="department" value="Some dept" />
<input id="position" value="Debt collector" />
<button type="submit">Submit</button>
</form>
This is no closure, if the variable in setupFormUI is referenced, it is a closure.
getRegistrationFormValue is just a variable whose function is passed directly to the event trigger (and is asynchronous), note that it is not executed in setupFormUI, nor is it defined in setupFormUI, When it is executed, it has nothing to do with setupFormUI.
Mike Zinn's answer defines an anonymous function in setupFormUI, which in turn refers to the variable in setupFormUI, which is a closure.

JavaScript form validation not working as intended

Good morning,
I'm working on some simple form validation. Whenever I submit my form, the error message appears, but I can repeatedly spam the button for numerous error messages. Is there a way I can change this to only show the error message once? I've also noticed that even if I populate both fields it will still flash quickly in my console with the error log but not show the error.
Can anyone tell me what I'm doing wrong here?
var uname = document.forms['signIn']['userame'].value;
var pword = document.forms['signIn']['password'].value;
function validateMe (e) {
if (uname.length || pword.length < 1 || '') {
var container = document.getElementById('error-container');
var errorMsg = document.createElement('div');
errorMsg.className = 'error-message';
errorMsg.innerHTML = '<span class="heading-large">Please enter a valid username or password</span>';
container.appendChild(errorMsg);
console.log('An error occured');
return false;
}
}
<form id="signIn" action='#'>
<div class="boxed left-floater">
<h1 class="heading-large margin-top">Sign in</h1>
<div id="error-container"></div>
<div class="form-group">
<label class="form-label-bold" for="username">Username</label>
<input class="form-control log-in-form-control" id="username" name="username" type="text">
</div>
<div class="form-group">
<label class="form-label-bold" for="password">Password</label>
<input class="form-control log-in-form-control" id="password" type="password" name="password">
</div>
<div>
<a class="right-floater forgotten-password" href="forgottenpassword.html">Forgotten Password</a>
<button class="button clear right-floater" type="submit" onclick="validateMe();">Sign In</button>
</div>
</div>
</form>
Fiddle
You must be clearing the contents of your container to avoid duplication of elements. Below are few things to note:
You were trying to get userame instead of username in your fiddle. May be spelling mistake.
Keep input type=submit instead of button
Pass the event to your validateMe function to prevent the default action of post.
Move the variables within the function to get the actual value all the time
function validateMe(e) {
e.preventDefault();
var uname = document.forms['signIn']['username'].value;
var pword = document.forms['signIn']['password'].value;
var container = document.getElementById('error-container');
container.innerHTML = ''; //Clear the contents instead of repeating it
if (uname.length < 1 || pword.length < 1) {
var errorMsg = document.createElement('div');
errorMsg.className = 'error-message';
errorMsg.innerHTML = '<span class="heading-large">Please enter a valid username or password</span>';
container.appendChild(errorMsg);
console.log('An error occured');
return false;
}
}
<form id="signIn" action='#'>
<div class="boxed left-floater">
<h1 class="heading-large margin-top">Sign in</h1>
<div id="error-container"></div>
<div class="form-group">
<label class="form-label-bold" for="username">Username</label>
<input class="form-control log-in-form-control" id="username" name="username" type="text">
</div>
<div class="form-group">
<label class="form-label-bold" for="password">Password</label>
<input class="form-control log-in-form-control" id="password" type="password" name="password">
</div>
<div>
<a class="right-floater forgotten-password" href="forgottenpassword.html">Forgotten Password</a>
<input value="Sign In" class="button clear right-floater" type="submit" onclick="validateMe(event);" />
</div>
</div>
</form>
Updated Fiddle
Edit - if condition was failing and have updated it accordingly
this is full work code
var uname = "";
var pword = "";
function validateMe(e) {
e.preventDefault();
uname = document.forms['signIn']['username'].value;
pword = document.forms['signIn']['password'].value;
if (uname.length || pword.length < 1 || '') {
var container = document.getElementById('error-container');
var errorMsg = document.createElement('div');
errorMsg.className = 'error-message';
errorMsg.innerHTML = '<span class="heading-large">Please enter a valid username or password</span>';
container.appendChild(errorMsg);
console.log('An error occured');
return false;
}
return true;
}
<form id="signIn">
<div class="boxed left-floater">
<h1 class="heading-large margin-top">Sign in</h1>
<div id="error-container"></div>
<div class="form-group">
<label class="form-label-bold" for="username">Username</label>
<input class="form-control log-in-form-control" id="username" name="username" type="text">
</div>
<div class="form-group">
<label class="form-label-bold" for="password">Password</label>
<input class="form-control log-in-form-control" id="password" type="password" name="password">
</div>
<div>
<a class="right-floater forgotten-password" href="forgottenpassword.html">Forgotten Password</a>
<button class="button clear right-floater" type="submit" onclick="validateMe(event);">Sign In</button>
</div>
</div>
</form>

My JavaScript form validation function is called two times

I am trying to print the value from the form when a user submits the function but a blank value is returned.
Here is my JavaScript code:
var login = new function()
{
var name = null ;
this.validation = function()
{
this.name = document.getElementById("Username").value;
console.log(this.name);
document.getElementById("demo").innerHTML = this.name;
};
};
And my HTML form as :
<body>
<div class="container">
<div class="col-md-8">
<div class="starter-template">
<h1>Login with javascript</h1>
<p class="lead">Please Enter Following Details</p>
<h1 id="demo"></h1>
<form name="form" onSubmit="return login.validation();" action="#" method="post">
<div class="form-group">
<label for="exampleInputEmail1">Username</label>
<input type="text" name="username" class="form-control" id="Username" placeholder="Please Enter your Username">
</div>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="Email" placeholder="Please enter your Password">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="Password" placeholder="Password">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Re-Password</label>
<input type="password" class="form-control" id="Re-Password" placeholder="Password">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
</div>
<script src="js/login.js"></script>
<script href="js/bootstrap.js"></script>
<!-- /.container -->
</body>
Why does the value not get into html <p> tag.
Your code simply works. But since the function executes on submitting the form, the username gets logged in the console fast before the page refreshed with submitted data. You can confirm this and test it by adding event.preventDefault(); to the function to prevent submitting the form so the page would stay visible with the console.
<script>
var login = new function()
{
var name = null ;
this.validation = function()
{
event.preventDefault();
this.name = document.getElementById("Username").value;
console.log(this.name);
document.getElementById("demo").innerHTML = this.name;
};
};
</script>
If that's not what you're looking for, let me know.
We the javascript validation failed you need to return false. If you don't it will proceed your form further. Thanks
var login = new function()
{
var name = null ;
this.validation = function()
{
this.name = document.getElementById("Username").value;
document.getElementById("demo").innerHTML = this.name;
return false;
};
};

How to use $asyncValidators with angularjs and set a warning message in the HTML

This is my first bigger form with validations and etc.
I've created a Registration form and I'm using ng-messages for validation. The problem is that I need to validate the username, does it already exist in the JSON server that we are using or it's available. Of course, if it's taken the warning pops out in the HTML where the username input is, if it's available the submit button is no more disabled (because the form will be $valid) and the user can register. I want to use angular-sanitize because I found this (I don't know if they are related):
ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
var value = modelValue || viewValue;
// Lookup user by username
return $http.get('/api/users/' + value).
then(function resolved() {
//username exists, this means validation fails
return $q.reject('exists');
}, function rejected() {
//username does not exist, therefore this validation passes
return true;
});
};
Here is the code I use now (reg form, controller and service):
// Controller:
export default class registerPageController {
constructor(userService, authenticationService, $location) {
this.register = "Register";
this.userService = userService;
this.$location = $location;
this.authenticationService = authenticationService;
this.hasLoggedIn = false;
}
onSubmit(user) {
let self = this;
let {
name,
age,
email,
username,
password
} = user;
self.userService.register(name, age, email, username, password).then((res) => {
self.userService.login(username, password).then(function (response) {
let data = response.data;
if (data.length) {
let user = data[0];
self.hasLoggedIn = true;
self.authenticationService.setCredentials(username, password);
self.$location.path('/');
}
});
})
.catch(err => {
// WHAT TO PUT HERE AFTER THE USERNAME EXIST VALIDATION ?
})
}
}
// Service:
export class UserService {
constructor($http) {
this.$http = $http;
}
login(username, password) {
return this.$http({
method: 'GET',
url: 'http://localhost:3000/users',
params: {
username: username,
password: password
}
});
}
register(name, age, email, username, password) {
return this.$http({
method: 'POST',
url: 'http://localhost:3000/users',
data: {
name: name,
age: age,
email: email,
username: username,
password: password
}
});
}
// SHOULD I PUT HERE THE USERNAME EXIST VALIDATION LOGIC ?
}
<div class="container main-content">
<form class="registrationForm" name="registerForm" ng-submit="register.onSubmit(register.user)" novalidate="novalidate">
<!-- Enter Name -->
<div class="form-group">
<label for="name" class="control-label"><span id="reqInfo">*</span> Name</label>
<input type="text" name="name" class="form-control" ng-model="register.user.name" ng-pattern="/[a-zA-Zа-яА-Я]+/" id="name"
required="" placeholder="Example: Petar Petrov">
<div ng-messages="registerForm.name.$error" ng-show="registerForm.name.$touched" style="color:maroon" role="alert">
<div ng-message="required">Your name is required</div>
</div>
</div>
<!-- User Age-->
<div class="form-group">
<label for="age" class="control-label"><span id="reqInfo">*</span> Age</label>
<input type="number" name="age" class="form-control" ng-model="register.user.age" ng-min="18" min="18" id="age" required=""
placeholder="Enter your age">
<div ng-messages="registerForm.age.$error" ng-show="registerForm.age.$touched" style="color:maroon" role="alert">
<div ng-message="min">You must be at leats 18 years old</div>
</div>
</div>
<!-- Enter E-mail -->
<div class="form-group">
<label for="email" class="control-label"><span id="reqInfo">*</span> E-mail</label>
<input type="email" name="email" class="form-control" ng-model="register.user.email" ng-pattern="/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+#)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+#)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%#\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/"
id="email" required="" placeholder="Example: mail#mail.net">
<div ng-messages="registerForm.email.$error" ng-show="registerForm.email.$touched" style="color:maroon" role="alert">
<div ng-message="required">Your valid e-mail is required</div>
</div>
<br>
<!-- Enter Username -->
<div class="form-group">
<label for="username" class="control-label"><span id="reqInfo">*</span> Username</label>
<input type="text" name="username" ng-minlength="5" ng-maxlength="20" class="form-control" ng-model="register.user.username"
ng-pattern="/^[A-Za-z0-9_]{1,32}$/" ng-minlength="7" id="username" required="" placeholder="Enter your username">
<div ng-messages="registerForm.username.$error" style="color:maroon" role="alert">
<div ng-message="minlength">Your Username must be between 7 and 20 characters long</div>
</div>
<br>
<!-- Enter Password -->
<div class="form-group">
<label for="password" class="control-label"><span id="reqInfo">*</span> Password</label>
<input type="password" name="password" class="form-control" ng-model="register.user.password" ng-minlength="7" id="password"
required="" placeholder="Enter your password">
<div ng-messages="registerForm.password.$error" style="color:maroon" role="alert">
<div ng-message="minlength">You Password must be at least 7 symbols long</div>
</div>
</div>
<!-- Register button -->
<div class="form-group">
<button class="btn btn-primary" type="submit" ng-disabled="!registerForm.name.$valid || !registerForm.age.$valid || !registerForm.email.$valid || !registerForm.username.$valid || !registerForm.password.$valid">Register</button>
</div>
<p>Fields with <span id="reqInfo">*</span> must be filled.</p>
</form>
</div>
Important is to know that I have being told explicitly to write it in ES6.
I have problem with the logic so look at my code and please fill it for me so I can use it and most important - learn it :S
Thank you so so much in advance!
I have implemented a directive for different kind of validations (sync Async), and it supports warning as well.
You may check it from
`https://plnkr.co/2WQHOo`
If this is what you needed and need more information, let me know I will try my best to answer.

Categories