Apply ngIf validity on submit - javascript

I validate a few fields in a form in my Angular 10 project like this:
<div class="question">
<div class="row">
<h5>1. Requestors Name (Your name or JHED ID)</h5><p class="required">*</p>
</div>
<input type="text" class="form-control" id="requestorName" name="requestorName" required minlength="2"
[(ngModel)]="model.requestorName" #requestorName="ngModel"/>
<div *ngIf="requestorName.invalid && (requestorName.dirty || requestorName.touched)"
class="alert">
<div *ngIf="requestorName.errors?.required">
<p class="required">Requester name is required.</p>
</div>
<div *ngIf="requestorName.errors?.minlength">
<p class="required">Requester name must be at least 2 characters long.</p>
</div>
</div>
</div>
Which works fine. However, if the user never touches the fields that have validation like this but fill out the rest of the form then click Submit it will still be acceptable.
I also have written my own validation check on submit like this:
<div class="question">
<button class="submit col-md-2" (click)="onSubmit()">Submit</button>
</div>
validateModel(accessRequest: AccessRequestModel) {
const validityCheck = {
isValid: true,
reason: null
};
validityCheck.isValid = true;
console.log(accessRequest);
if (accessRequest) {
if (!accessRequest.requestorName) {
validityCheck.isValid = false;
validityCheck.reason = 'Requester name is required.';
return validityCheck;
} else if (!accessRequest.lname) {
validityCheck.isValid = false;
validityCheck.reason = 'Last name is required.';
return validityCheck;
}
else if (!accessRequest.fname) {
validityCheck.isValid = false;
validityCheck.reason = 'First name is required.';
return validityCheck;
}
else if (!accessRequest.department) {
validityCheck.isValid = false;
validityCheck.reason = 'Department is required.';
return validityCheck;
}
else if (!accessRequest.title) {
validityCheck.isValid = false;
validityCheck.reason = 'Job title is required.';
return validityCheck;
}
else if (!accessRequest.managerName) {
validityCheck.isValid = false;
validityCheck.reason = 'Manager name is required.';
return validityCheck;
}
else if (!accessRequest.startDate) {
validityCheck.isValid = false;
validityCheck.reason = 'Start date is required.';
return validityCheck;
}
else if (!accessRequest.accessType) {
validityCheck.isValid = false;
validityCheck.reason = 'Access type is required.';
return validityCheck;
}
}
return validityCheck;
}
Which also works.
But what I want is for the same error messages that apply if you do click on the boxes to apply if the validity check function returns false. How could I do that?
If the question wasn't clear or you need additional information please let me know.

Seems like you are trying to recreate form validation. Look into reactive forms module in angular and do the following:
Import ReactiveFormsModule into the module where your component is defined
Dependency Inject it to your component's constructor like so:
constructor(private formBuilder: FormBuilder) {}
Define the form creation logic in your OnInit method:
ngOnInit() {
this.myForm = this.formBuilder.group({
option1: ['', Validators.Required],
...
})
}
Update your HTML to leverage this new form based on the documentation that angular provides. Thus your submit button can define a [disabled] attribute that sets a button as disabled if the form is not valid. The syntax in the form group of: [{initialValue}, {validator | array of validators}] is what controls the validity of the input.
Conversely, you can also iterate over each control in the form and manually set the error state for it by calling the setError method on the FormControl object if you still want to enable a user to click submit even on an invalid form input.

Related

How to solve blur and submit event simultaneous in angular

I have text box in my page, which i can enter 9 digit number. Onblur I am validating like the entered number is valid or not using API call, If service returns failure it will clear the text box with red border and form will be invalid. The event conflict happening between OnBlur and Submit. Submit service will call only the form is valid otherwise it will show toaster like enter mandatory filed.
If the text field focused and directly if I click on submit button, both event calling simultaneously and it is clearing the number field OnBlur as well as the service is calling.
Please can you help me to resolve this conflicts.
file.html
<form class="contact-form" #create="ngForm">
<div class="controls">
<input NumberOnly="true" type="text" id="num" [ngClass]="{'red-border-class': ((showErrorFlag == true && numberField.errors) || (showErrorFlag == true && numberField.errors && (numberField.dirty || numberField.touched)))}"
[disabled]="disableRotaDetailFields" [(ngModel)]="number"
class="floatLabel" name="ownership" required #numberField="ngModel" (blur)="validatenumber(number)" [maxLength]="einLength">
<label for="ein">number<sup>*</sup></label>
</div>
<button (click)="SaveData(create)">Save</button>
</form>
file.ts
public validatenumber(number) {
let reqObj = {
"ownership": number
}
this.calloutService.validateOwnerEin(reqObj)
.pipe(takeUntil(this.unsubscribe))
.subscribe((data) => {
}, (err) => {
if (err.status == 404) {
this.number = "";
}
this.toastr.error(err.overriddenMessage);
})
}
SaveData(){
if (!formFlag.valid ) {
this.showErrorFlag = true;
this.toastr.error('Please fill all the mandatory fields');
}else {
this.calloutService.createData(this.data)
.pipe(takeUntil(this.unsubscribe))
.subscribe(data => {
this.showSpinnerFlag = false;
let response = data;
if (data) {
this.toastr.success("Rota created successfully.");
} else {
this.toastr.error("Could not save.");
}
}, err => {
this.showSpinnerFlag = false;
this.toastr.error(err.overriddenMessage);
})
}
}

Angular Custom Validator Doesn't Reflect Changes in View

I have custom validator like this:
export class PasswordValidator {
static MatchPassword(AC: AbstractControl) {
const formGroup = AC.parent;
if(formGroup) {
let password = formGroup.value.password // to get value in input tag
let confirmPassword = formGroup.value.confirmPassword; // to get value in input tag
if(password != confirmPassword) {
formGroup.get('confirmPassword').setErrors({ matchPassword: true });
} else {
formGroup.get('confirmPassword').setErrors(null);
}
console.log(formGroup.get('confirmPassword').errors);
} else {
return null
}
}
}
And i have added to the form:
this.registerationForm.addControl("confirmPassword", new FormControl('', Validators.compose([Validators.required, PasswordValidator.MatchPassword])));
And in View:
<ion-item class="error-message" *ngIf="registerationForm.controls.confirmPassword.hasError('matchPassword')
&& registerationForm.controls.confirmPassword.touched">
<p>Some message*</p>
</ion-item>
But the problem is i can see the console window but i don't see it reflects in view. The ngIf condition isn't showing the error message
Use detectChanges() when you've updated the model after angular has run it's change detection, or if the update hasn't been in angular world at all.
Use markForCheck() if you're using OnPush and you're bypassing the ChangeDetectionStrategy by mutating some data or you've updated the model inside a setTimeout;
export class PasswordValidator {
static MatchPassword(AC: AbstractControl) {
const formGroup = AC.parent;
if(formGroup) {
let password = formGroup.value.password // to get value in input tag
let confirmPassword = formGroup.value.confirmPassword; // to get value in input tag
if(password != confirmPassword) {
formGroup.get('confirmPassword').setErrors({ matchPassword: true });
} else {
formGroup.get('confirmPassword').setErrors(null);
}
console.log(formGroup.get('confirmPassword').errors);
this.ref.markForCheck();
} else {
return null
}
}
}
add this.ref.markForCheck(); after you update the form.

Validation of multiple empty field

I am trying to validate two fields in my form.
But it is displaying the error message only for one field.
Following is Javascript code:
function req() {
if (document.reg_indi_form.txt_fnm.value=="") {
document.getElementById('i').innerHTML="*This field is required";
document.getElementById('i').style.color="red";
return false;
}
if (document.reg_indi_form.txt_lnm.value=="") {
document.getElementById('i1').innerHTML="*This field is required";
document.getElementById('i1').style.color="red";
return false;
}
}
HTML code:
<input name="txt_fnm" type="text" id="txt_fnm"/> <label id="i"></label>
<input name="txt_lnm" type="text" id="txt_lnm"/>\<label id="i1"></label>
If you need to get all errors tested, as "Disha" commented, you can not put a return statement in each if blocks.
var noError = true;
if (document.reg_indi_form.txt_fnm.value=="") {
document.getElementById('i').innerHTML="*This field is required";
document.getElementById('i').style.color="red";
noError = false;
}
if (document.reg_indi_form.txt_lnm.value=="") {
document.getElementById('i1').innerHTML="*This field is required";
document.getElementById('i1').style.color="red";
noError = false;
}
return noError;
That should work as you seems to want to.
Try This Code
JavaScript
`
function validate(){
var isValid = true;
if (document.reg_indi_form.txt_fnm.value=="") {
document.getElementById('i').innerHTML="*This field is required";
document.getElementById('i').style.color="red";
isValid = false;
}
if (document.reg_indi_form.txt_lnm.value=="") {
document.getElementById('i1').innerHTML="*This field is required";
document.getElementById('i1').style.color="red";
isValid = false;
}
return isValid;
}`

Form Validation not working on all fields but only the first

When i post form only the title validation is working, the other two fields are not validated.
HTML
<form name="qaform" class="nice" method="POST" onsubmit="validateForm()" action="/ask/ask-question/">
<input type="hidden" id="id_selected_tags" name="tags">
<p>
<label for="id_title" class="inline-block">Title</label>
<input type="text" class="input-text inline-block" id="id_title" name="question_title">
</p>
<span id="error_title"></span>
<textarea id="id_question" name="question_description" class="full-width"></textarea>
<span id="error_body"></span>
<p>
<label for="id_tags" class="inline-block">Tags</label>
<input type="text" id="id_newstagbox" name="question_tags"/>
</p>
<span id="error_tags"></span>
<button class="btn btn-success" type="submit">Post your question</button>
</form>
JS
function validateForm()
{
//title validation
if (document.qaform.question_title.value == "") {
document.getElementById('error_title').innerHTML="*Please add a title*";
return false;
}
//body validation
if (document.qaform.question_description.value == "") {
document.getElementById('error_body').innerHTML="*Please add a description*";
return false;
}
//tag validation
if (document.qaform.question_tags.value == "") {
document.getElementById('error_tags').innerHTML="*Please add a description*";
return false;
}
}
After submitting the forms post successfully if title is present.
The stackoverflow form validation forced me to do this, its constantly saying me to add more text because my question contains mostly code.I know its good to provide more information about question but there are times when you can ask a question in few words without being too broad and then you have to rant about it to pass the FORM VALIDATION.
Just remove return false.modify it like below
<script>
function validateForm()
{
var x=document.forms["myForm"]["fname"].value;
var y=document.forms["myForm"]["farea"].value;
var z=document.forms["myForm"]["ftag"].value;
if (x==null || x=="")
{
document.getElementById('ern').innerHTML="*Please add a title*";
}
if (y==null || y=="")
{
document.getElementById('era').innerHTML="*Please add a desxription*";
}
if (z==null || z=="")
{
document.getElementById('ert').innerHTML="*Please add a tag*";
}
}
</script>
I prefer using jQuery:
$('#form').submit(function(e) {
var validated = true;
e.preventDefault();
//title validation
if ($('#id_title').val() == "") {
$('#error_title').html("*Please add a title*");
validated = false;
}
//body validation
if ($('#id_question').val() == "") {
$('#error_body').html("*Please add a description*");
validated = false;
}
//tag validation
if ($('#id_newstagbox').val() == "") {
$('#error_tags').html("*Please add a description*");
validated = false;
}
if(validated) {
$(this).unbind('submit').submit();
}
});
You just remove your return false inside each condition,
check this jsfiddle how it works if you remove return false line.
Note:Return false will stop your execution there
Remove the "return false" in the if clauses. This stops your function and the other if clauses wouldn´t get called.
just add 'return' keyword before validateform()
like this
<form name="qaform" class="nice" method="POST" onsubmit="return validateForm()" action="/ask/ask-question/">
Try making these 5 small changes to your validateForm method -
function validateForm() {
var valid = true; // 1
//title validation
if (document.qaform.question_title.value == "") {
document.getElementById('error_title').innerHTML="*Please add a title*";
valid = false; // 2
}
//body validation
if (document.qaform.question_description.value == "") {
document.getElementById('error_body').innerHTML="*Please add a description*";
valid = false; // 3
}
//tag validation
if (document.qaform.question_tags.value == "") {
document.getElementById('error_tags').innerHTML="*Please add a description*";
valid = false; // 4
}
return valid; // 5
}
i think the reason why it only validates the first one, is because you return false to exit the validate function, if you do the return false after all the if loops i think it will do what you want.

Alerts conditional on model validation

I have an Picture model with various validations:
validates :title, presence: true
validates :caption, presence: true
validates :image, presence: true
validates :price, numericality: { greater_than_or_equal_to: 1, less_than_or_equal_to: 1000 }
validates_size_of :tag_list, :minimum => 3, :message => "please add at least three tags"
The tag list has to be submitted in a specific format: at least three tags, separated by a comma and a space: eg foo, bar, cats
I want to have an alert that tells the user to "please wait, we're uploading your image" - but only AFTER the model has passed ALL of the validations ( before the .save in the controller)
Is there a way of doing this in the controller, which I'd prefer, or do I have to use some javascript like:
$("form#new_picture").on("submit", function () {
if LOTS OF HORRIBLE REGEX ON FORM FIELDS {
MESSAGE HERE
return true;
} else {
return false;
}
});
OR Is there a way of doing this in the model, as part of an after_validation callback?
Any suggestions much appreciated. Thanks in advance.
I would build a JS function to extract the fields that I want to be validated.
Then create a custom AJAX controller action, which:
instantiates a new object with given params
call valid? on it without saving it
Then:
On failure, update the form with error messages
On success, I would return a custom ajax response to display the alert and start POSTing the real object.
I've realised that this isn't really possible through through the model or controller, and resorted to a combination of three validation processes:
Validations in the model
The simpleform client side validations gem - this is v good, it tests validity the moment a form field loses focus - "real time" validation.
And some additional javascript to alert with popups and errors, pasted below.
Hopefully this makes the form virtually un-submittable without the user knowing what's missing.
THE JS SOLUTION
FORM
<form id="new_pic" novalidate>
<p><input type="file" name="file" required></p>
<p><input type="string" name="name" placeholder="Name" required></p>
<p><input type="string" name="tags" placeholder="Tags" data-validation="validateTags"></textarea></p>
<p><textarea name="description" data-validation="validateDescription"></textarea></p>
<p><button type="submit">Submit</button>
</form>
JS
var Validator = function(form) {
this.form = $(form);
}
$.extend(Validator.prototype, {
valid: function() {
var self = this;
this.errors = {};
this.form.find('[required]').each(function() {
self.validateRequired($(this));
});
this.form.find('[data-validation]').each(function() {
var el = $(this),
method = el.data('validation');
self[method].call(self, el);
});
return $.isEmptyObject(this.errors);
},
validateRequired: function(input) {
if (input.val() === '') {
this.addError(input, 'is required');
}
},
validateDescription: function(input) {
if (input.val().length < 64) {
this.addError(input, 'must be at least 64 characters');
}
},
validateTags: function(input) {
var tags = input.val().split(/, ?/);
if (tags.length < 3) {
this.addError(input, 'must have at least 3 tags');
}
},
addError: function(input, error) {
var name = input.attr('name');
this.errors[name] = this.errors[name] || [];
this.errors[name].push(error);
input.after('<span class="error">' + error + '</span>');
}
});
$('form#new_pic').on('submit', function(event) {
event.preventDefault();
var form = $(this),
validator = new Validator(form);
form.find('.error').remove();
if (validator.valid()) {
// continue with upload
alert('Go!');
return true;
} else {
// complain
alert('Stop!');
return false;
}
});

Categories