validate input text with angularJS - html

I've got a form which adds items in my todo list array.
However if the input field is empty, my function is adding an empty value to my array.
What is the best way to validate the form?
<form name="formaddtodo" ng-submit="todoList.addTodo()">
<input type="text" ng-model="todoList.todoText" ng-minlength="1" size="30"
placeholder="Voeg nieuwe todo toe">
<input class="btn-primary" type="submit" value="voeg toe">
</form>
Here is my function
todoList.addTodo = function() {
todoList.todos.push({text:todoList.todoText, done:false});
todoList.todoText = '';
};
There is no validation yet but I'm curious what the best way is to validate.
Thank you in advance!

You can use the built-in ngRequired directive:
<input type="text" ng-model="todoList.todoText" ng-minlength="1" size="30"
placeholder="Voeg nieuwe todo toe" ng-required="required">
AngularJS provides basic implementation for most common HTML5 input
types: (text, number, url, email, date, radio, checkbox), as well as
some directives for validation (required, pattern, minlength,
maxlength, min, max).
https://docs.angularjs.org/guide/forms

<form name="formaddtodo" ng-submit="todoList.addTodo(formaddtodo.$valid)">
<input type="text" ng-model="todoList.todoText" ng-minlength="1" size="30"
placeholder="Voeg nieuwe todo toe" required>
<input class="btn-primary" type="submit" value="voeg toe">
</form>
todoList.addTodo = function(isValid) {
if(isValid) {
todoList.todos.push({text:todoList.todoText, done:false});
todoList.todoText = '';
}
};
I think the above code will help you to validate your form.

ngMessages module support for displaying messages to the user for form validation.
ngMessages, developers were forced to rely on directives such as ng-class and ng-show to display these errors.
Please follow this link. It might be useful for you now and in future use for validation with AngulerJS.

Related

Is there a way to enable the autocomplete for angular reactive form?

I want to set on the autocomplete attribute for an angular form but it doesn't work as expected. It remembers only the values that I submitted only the first time and I would like to remember and suggest all the values no matter how many times I click on submit button.
Here is the stackblitz with the code that I tried.
<form
autocomplete="on"
(ngSubmit)="onSubmit()"
name="filtersForm"
[formGroup]="formGroup1"
>
<div>
<label>First Name</label>
<input
id="firstName"
name="firstName"
autocomplete="on"
formControlName="firstName"
/>
</div>
<div>
<label>Last Name</label>
<input
id="firstName"
name="lastName"
autocomplete="on"
formControlName="lastName"
/>
</div>
<button type="submit">Submit</button>
</form>
Here are the details about the autocomplete attribute that I used.
In Firefox, the autocomplete is working after several clicks on Submit button, the problem is in Chrome and Edge.
Is there a way to make the autocomplete to work for inputs inside the angular form?
I think, I have found a workaround, that only works with Template Driven Form.
TLDR;
What I have discovered while looking after this issue.
On first form submit autofill remember only first time submission values
form submit POST method can remember all values.
Yes, by looking at above, it clearly seems like 2nd way is suitable for us. But why would anybody do form POST for submitting form to BE. There should be better way to tackle this. Otherwise we would have to think of handling PostBack 😃😃 (FW like .Net does it by keeping hidden input's).
Don't worry we can do some workaround here to avoid form POST. I found an answer for handling POST call without page refresh.
Working JSBin with plain HTML and JS
AutoCompleteSaveForm = function(form){
var iframe = document.createElement('iframe');
iframe.name = 'uniqu_asdfaf';
iframe.style.cssText = 'position:absolute; height:1px; top:-100px; left:-100px';
document.body.appendChild(iframe);
var oldTarget = form.target;
var oldAction = form.action;
form.target = 'uniqu_asdfaf';
form.action = '/favicon.ico';
form.submit();
setTimeout(function(){
form.target = oldTarget;
form.action = oldAction;
document.body.removeChild(iframe);
});
}
Basically we change set few things on form attribute.
target="iframe_name" - Connects to iFrame to avoid page refresh.
method="POST" - POST call
url="/favicon" - API url to favicon (lightweight call)
In angular you can create an directive for the same.
import {
Directive, ElementRef, EventEmitter,
HostBinding, HostListener, Input, Output,
} from '#angular/core';
#Directive({
selector: '[postForm]',
})
export class PostFormDirective {
#HostBinding('method') method = 'POST';
#HostListener('submit', ['$event'])
submit($event) {
$event.preventDefault();
this.autoCompleteSaveForm(this.el.nativeElement);
}
constructor(private el: ElementRef) {}
autoCompleteSaveForm(form) {
let iframe = document.querySelector('iframe');
if (!iframe) {
iframe = document.createElement('iframe');
iframe.style.display = 'none';
}
iframe.name = 'uniqu_asdfaf';
document.body.appendChild(iframe);
var oldTarget = form.target;
var oldAction = form.action;
form.target = 'uniqu_asdfaf';
form.action = '/favicon.ico'; // dummy action
form.submit();
setTimeout(() => {
// set back the oldTarget and oldAction
form.target = oldTarget;
form.action = oldAction;
// after form submit
this.onSubmit.emit();
});
}
#Output() onSubmit = new EventEmitter();
ngOnDestroy() {
let iframe = document.querySelector('iframe');
if (iframe) {
document.body.removeChild(iframe);
}
}
}
Okay, so far everything went well. Then I started integrating this in formGroup(Model Driven Form), somehow it didn't worked. It does not store value next time these fields.
<form (ngSubmit)="onSubmit()" [formGroup]="formGroup1" autocomplete="on">
<div>
<label>First Name</label>
<input id="firstName" name="firstName" formControlName="firstName" />
</div>
<div>
<label>Last Name</label>
<input id="lastName" name="lastName" formControlName="lastName" />
</div>
<button>Submit</button>
</form>
Later I tried the same with Template Driven Form. It just worked like a charm! I did not went into the depth why it didn't work for Model Driven Form (perhaps that investigation could eat more time).
<form #form1="ngForm" ngForm postForm (onSubmit)="onSubmit(form1)">
<ng-container [ngModelGroup]="userForm">
<div>
<label>First Name</label>
<input name="firstName" [(ngModel)]="userForm.firstName" />
</div>
<div>
<label>Last Name</label>
<input name="lastName" [(ngModel)]="userForm.lastName" />
</div>
</ng-container>
<button>Submit</button>
</form>
Yeah, I just said in the begining it works only with Template Driven Form. So you would have to switch to Template. And one more important thing to note, you may think of creating dummy POST api call, that can be lightweight rather than hitting favicon.
Stackblitz
autocomplete attribute works only with submitted values. It has nothing to do with Angular.
https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete
If you need some custom behavior then you are better off creating your own component to autocomplete user's input, this way you can use some default values, add more of them on blur etc.
You just need to remove autocomplete="on" in input tag. With chrome, we only add attribute autocomplete="on" in form element and it will be cached all value that user input into input text. Result will be like this:
<form
autocomplete="on"
(ngSubmit)="onSubmit()"
name="filtersForm"
[formGroup]="formGroup1"
>
<div>
<label>First Name</label>
<input
id="firstName"
name="firstName"
formControlName="firstName"
/>
</div>
<div>
<label>Last Name</label>
<input
id="firstName"
name="lastName"
formControlName="lastName"
/>
</div>
<button type="submit">Submit</button>
</form>
You have to create an array with your desired options which should be displayed as autocomplete. You can have a look here https://material.angular.io/components/autocomplete/examples, there are multiple examples which should help you. Even if you're not using Angular Material, the logic would be the same

HTML form submits an empty string when JavaScript indicates the hidden control has a value

Amongst many other controls, I have the following HTML elements on a form
<input ID='cmdRegisterMe' name='cmdRegisterMe' value='Register Me' onclick="return preSubmit();" type='submit' />
<input type="hidden" ID="NewHash" name="NewHash" value="">
<INPUT TYPE="TEXT" ID="email" NAME="email" VALUE="" SIZE="50" MAXLENGTH="50">
<INPUT TYPE="PASSWORD" ID="password1" NAME="password1" VALUE="" SIZE="30" MAXLENGTH="25">
<INPUT TYPE="PASSWORD" ID="password2" NAME="password2" VALUE="" SIZE="30" MAXLENGTH="25">
and JS functions
function preSubmit() {
document.getElementById("NewHash").value = doNewHash(document.getElementById("password1").value, document.getElementById("email").value.toLowerCase());
alert(document.getElementById("NewHash").value);
document.getElementById("password1").value = '';
document.getElementById("password2").value = '';
return true;
}
function doNewHash(pw, strUsername) {
var hash_padding = '************';
return SHA1(SHA1(pw) + hash_padding + strUsername);
}
When I click Submit, I see the expected hashed value displayed by the call of alert().
However, in my PHP, the value of $_POST['NewHash'] is an empty string. I cannot fathom why this happens. In my understanding, there is no other code executed after the onclick() function returns true. I have done a global search on my code for 'NewHash' and there are no other assignments to it.
If I replace this line
document.getElementById("password1").value = '';
with this
document.getElementById("password1").value = document.getElementById("NewHash").value;
and inspect $_POST['password1'], it contains the hash value. What on earth could be happening to wipe out the value of 'NewHash'?
I have found what was wrong, but I hope posting the question may help someone else. I saved the PHP-generated HTML as a file, added to the top, and resolved to remove code piece by piece and submit until the submitted value for NewHash was no longer empty. I found I had TWO hidden controls called NewHash - so JS was displaying the value in one, and the browser was submitting the other!

Change the default HTML5 validation message language [duplicate]

I am trying to change the language of the error message in the html5 form field.
I have this code:
<input type="text" name="company_name" oninvalid="setCustomValidity('Lütfen işaretli yerleri doldurunuz')" required />
but on submit, even the field is not blank, I still get the error message.
I tried with <input type="text" name="company_name" setCustomValidity('Lütfen işaretli yerleri doldurunuz') required />
but then the english message is displayed. Anyone know how can I display the error message on other language?
Regards,Zoran
setCustomValidity's purpose is not just to set the validation message, it itself marks the field as invalid. It allows you to write custom validation checks which aren't natively supported.
You have two possible ways to set a custom message, an easy one that does not involve Javascript and one that does.
The easiest way is to simply use the title attribute on the input element - its content is displayed together with the standard browser message.
<input type="text" required title="Lütfen işaretli yerleri doldurunuz" />
If you want only your custom message to be displayed, a bit of Javascript is required. I have provided both examples for you in this fiddle.
your forget this in oninvalid, change your code with this:
oninvalid="this.setCustomValidity('Lütfen işaretli yerleri doldurunuz')"
<form><input type="text" name="company_name" oninvalid="this.setCustomValidity('Lütfen işaretli yerleri doldurunuz')" required /><input type="submit">
</form>
HTML:
<form id="myform">
<input id="email" oninvalid="InvalidMsg(this);" name="email" oninput="InvalidMsg(this);" type="email" required="required" />
<input type="submit" />
</form>
JAVASCRIPT :
function InvalidMsg(textbox) {
if (textbox.value == '') {
textbox.setCustomValidity('Lütfen işaretli yerleri doldurunuz');
}
else if (textbox.validity.typeMismatch){
textbox.setCustomValidity('Lütfen işaretli yere geçerli bir email adresi yazınız.');
}
else {
textbox.setCustomValidity('');
}
return true;
}
Demo :
http://jsfiddle.net/patelriki13/Sqq8e/4
This work for me.
<input oninvalid="this.setCustomValidity('custom text on invalid')" onchange="this.setCustomValidity('')" required>
onchange is a must!
I know this is an old post but i want to share my experience.
HTML:
<input type="text" placeholder="Username or E-Mail" required data-required-message="E-Mail or Username is Required!">
Javascript (jQuery):
$('input[required]').on('invalid', function() {
this.setCustomValidity($(this).data("required-message"));
});
This is a very simple sample. I hope this can help to anyone.
TLDR: Usually, you don't need to change the validation message but if you do use this:
<input
oninvalid="this.setCustomValidity('Your custom message / 您的自定义信息')"
oninput="this.setCustomValidity('')"
required="required"
type="text"
name="text"
>
The validation messages are coming from your browser and if your browser is in English the message will be in English, if the browser is in French the message will be in French and so on.
If you an input for which the default validation messages doesn't work for you, the easiest solution is to provide your custom message to setCustomValidity as a parameter.
...
oninvalid="this.setCustomValidity('Your custom message / 您的自定义信息')"
...
This is a native input's method which overwrites the default message. But now we have one problem, once the validation is triggered, the message will keep showing while the user is typing. So to stop the message from showing you can set the validity message to empty string using the oninput attribute.
...
oninput="this.setCustomValidity('')"
...
//Dynamic custome validation on all fields
//add validate-msg attr to all inputs
//add this js code
$("form :input").each(function(){
var input = $(this);
var msg = input.attr('validate-msg');
input.on('change invalid input', function(){
input[0].setCustomValidity('');
if(!(input[0].validity.tooLong || input[0].validity.tooShort)){
if (! input[0].validity.valid) {
input[0].setCustomValidity(msg);
}
}
});
});
<input type="text" id="inputName" placeholder="Enter name" required oninvalid="this.setCustomValidity('Your Message')" oninput="this.setCustomValidity('') />
this can help you even more better, Fast, Convenient & Easiest.
For the lost souls who are seeking a way to fully localize their error messages, see the snippet below. In short, you have to switch over the properties of event.target.validity and override the corresponding error message using event.target.setCustomValidity(message). If you just care about the empty field case as OP, just consider the case of valueMissing.
Note that the handler is passed in the React way, but other answers already covered how to do it in vanilla JS.
For the meaning of each validity state and how to implement customized error messages, see MDN: Validating forms using JavaScript.
const handleInvalidForm = (event) => {
const { patternMismatch,
tooLong,
tooShort,
rangeOverflow,
rangeUnderflow,
typeMismatch,
valid,
valueMissing } = event.target.validity;
if (patternMismatch)
event.target.setCustomValidity('...');
else if (tooLong)
event.target.setCustomValidity('...');
else if (tooShort)
event.target.setCustomValidity('...');
else if (rangeOverflow)
event.target.setCustomValidity('...');
else if (rangeUnderflow)
event.target.setCustomValidity('...');
else if (typeMismatch)
event.target.setCustomValidity('...');
else if (valid)
event.target.setCustomValidity('...');
else if (valueMissing)
event.target.setCustomValidity('...');
}
// ...
<form onSubmit={handleFormSubmit}
onInvalid={handleInvalidForm}
>
{emailTextField}
{passwordTextField}
{signInButton}
</form>
<input type="text" id="inputName" placeholder="Enter name" required oninvalid="this.setCustomValidity('Please Enter your first name')" >
this can help you even more better, Fast, Convenient & Easiest.
Do it using JS. Grab the class of the error message, and change it's content for whereever it appears.
var myClasses = document.getElementsByClassName("wpcf7-not-valid-tip");
for (var i = 0; i < myClasses.length; i++) {
myClasses[i].innerHTML = "Bitte füllen Sie das Pflichtfeld aus.";
}
<form>
<input
type="text"
name="company_name"
oninvalid="this.setCustomValidity('Lütfen işaretli yerleri doldurunuz')"
required
/><input type="submit" />
</form>

output all members of a form (form.FormController)

Please see the code here
it is an angular form, and the variable form should be of FormController . As you see with the usage of form.$pristine, the variable $pristine exists in form, but why it doesn't output when I just try <pre>form = {{form}}</pre>. I wanted to see all the members (if possible function names, else at least all primitives like $dirty, $valid , etc.) Why it is not outputting in the pre tag and how can I show them? It is mainly for debugging, but curious as well.
<form novalidate name="form" class="simple-form">
Name: <input type="text" ng-model="user.name" /><br />
E-mail: <input type="email" ng-model="user.email" /><br />
Gender: <input type="radio" ng-model="user.gender" value="male" />male
<input type="radio" ng-model="user.gender" value="female" />female<br />
<button ng-click="reset()">RESET</button>
<button ng-click="update(user)">SAVE</button>
</form>
<pre>pristine = {{form.$pristine}}</pre>
<pre>form = {{form}}</pre>
output
pristine = true
form = {}
An expression like this: {{form}} will convert the form object to a string. Angular uses the build in angular.toJson function to serialize the object. Please have a look at the documentation: angular.toJson. As you can see there all properties with a leading $ are stripped.
How to solve your problem:
You may use the JSON.stringify function to get all properties. Because you can't call this function in an expression you need to provide a helper function in your controller:
$scope.stringify = function(obj){
return JSON.stringify(obj);
}
Now you are able to output your complete form object in the view:
{{stringify(form)}}
The following should also work...
<pre>form = {{form | json}}</pre>

Call a function after Html5 Validation success

I have Some text boxes and one submit button. I have Used HTML5 'required' validation. Its working fine. Now I want to call a function in button click when HTML5 validation does not find any Error. When The required field is not provided the button click will not call the function.
You can use the form.onsubmit handler. Assuming the form's ID is form:
var form = document.getElementById("form");
form.onsubmit = function() {
//Pre-submission validation.
//Return true or false based on whether the validation passed.
//return false will prevent the submission the form.
};
You're going to need some extra help to do this, it could be in the form of plain javascript. Personally, I'd use jQuery to help out as it will make things easier for you and account for any cross-browser consistencies. Whether or not you want to use jQuery your is choice, whether it's appropriate only for this is another conversation, the following example is just a demonstration.
Here's a hypothetical example using jQuery that achieves your validation listening functionality:
HTML
<form>
<input type="text" class="input-text" required>
<input type="text" class="input-text" required>
<input type="submit" id="submit" class="input-button" disabled>
</form>
​
JS
$textInputs = $('input.input-text');
$textInputs.on('keyup', function() {
var $validTextInputs = $('input.input-text:valid'),
$submit = $('#submit');
console.log($textInputs.length, $validTextInputs.length);
if($textInputs.length === $validTextInputs.length){
//all text fields are valid
$submit.attr('disabled', null);
} else {
//not all text fields are valid
$submit.attr('disabled', '');
}
});​
CSS (only let's us know, visually, when the input is valid)
.input-text:valid {
background: green;
}​
See the example in action here: http://jsfiddle.net/m6QXc/
Use jquery to trigger function after HTML5 form validation
<form id="myForm">
<input type="text" class="input-text" required>
<input type="submit" id="submit" class="input-button" disabled>
</form>
$("myForm").submit(function(){
// Your code
})
Well, you could try this: fiddle example extend it as you need, used jQuery though. You can add whatever you want inside:
$('#exampleForm').submit(function(e){
e.preventDefault();
// here you can call your own js methods, send form with ajax?
// or what ever you want
});