Iām new to Vue.
I would like to know if it is possible to update the input value after running a custom validation in Vuelidate. I have an input field for postcode. I want to return the postcode with the correct format in case the user forgets to put a whitespace, and update the input field with the correct value, e.g.
user input = XXXXXX
returned output = XXX XXX
Sample code
export default {
...
validations: {
postcode: {
required,
maxLength: maxLength(10),
validatePostcode: (value) => {
const result = customValidators.validatePostcode(value);
if (result !== false) {
if (result !== value) {
// UPDATE THE INPUT VALUE HERE WITH THE CORRECT POSTCODE FORMAT
}
return true;
}
return false;
}
}
}
...
}
I changed the arrow function declaration to a function shorthand declaration. I'm now able to access the component object and change the input field value via the Vuelidate model. Thanks to this: https://github.com/vuelidate/vuelidate/issues/237 š
Related
In a table of records, there are certain input text fields and date field which can be changed. When input text is changed date field gets undefined and for date field its vice-versa. My intention is to pass values of input text as well as date values, but, gets undefined in the console. Please refer to code below
const handleChange = (data) => {
// here text and date values are extracted
const { id, textVal, dateVal } = data;
setDataNew((prevInfo) => {
const newList = [...prevInfo];
const index = newList.findIndex((datum) => datum.id === id);
if (index !== -1) {
// getting undefined here
newList[index] = { id, textVal, dateVal };
} else {
newList.push({ id, textVal, dateVal });
}
return [...newList];
});
};
I'm able to process data only when input text is changed, but, on date field change input data is undefined... similarly it happens for date field as well.
Please refer to codesandbox link for better clarity --> https://codesandbox.io/s/elated-varahamihira-xpjtdb?file=/src/Table.js:968-1155
You will have to pass other value from the Grid component in the callback of date change and name change.
Hi am using angular 2 forms,
I have an inout field to key in users GSTIN value.
GSTIN format is XX-XXXXXXXXXX-X-X-X alphanumeric. What i need achieve is once the user keyin the values, I need to add a hyphen in to the keyed in value as per the format mentioned above.
HTML:
<custom-input [autocomplete]="false" [type]="'text'" [autocapitalize]="true" (change)="onGstinValChange($event)" (focusout)="onChangeGSTIN($event)"
[maxlength]="15" [formControl]="enterpriseDetailForm.controls['GSTIN']"
(ngModelChange)="mychange($event)"
[ngModel]="iban_no"></custom-input>
TS:
mychange(val) {
if (val) {
const self = this;
let gstin = val.split('-').join('');
if (gstin.length > 0) {
gstin = gstin.match(new RegExp('.{1,2}', 'g')).join('-');
}
console.log(gstin);
this.dataGstin = gstin;
}
}
With this function i can split every 2 values. Can someone help me on how i can achieve my format mentioned above? Thanks in advance.
Dont mix Reactive form approach with the Template drive form approach , just use one
so if you go with reactive form apporch then code will be
<custom-input [autocomplete]="false" [type]="'text'" [autocapitalize]="true" (change)="onGstinValChange($event)" (focusout)="onChangeGSTIN($event)"
[maxlength]="15" [formControl]="GSTIN"
></custom-input>
there is no need of (ngModelChange)="mychange($event)" [ngModel]="iban_no" as its template driven attributes
onGstinValChange($event){
let inputtext = $event.Traget.value;
///do code for adding - as per formate
enterpriseDetailForm.get('GSTIN').setValue(inputtext);
}
or just use reactive monitor change in value
ngOnInit() {
this.enterpriseDetailForm.get('GSTIN').valueChanges.subscribe(val =>
{
let gstin = val.split('-').join('');
if (gstin.length > 0) {
gstin = gstin.match(new RegExp('.{1,2}', 'g')).join('-');
}
enterpriseDetailForm.get('GSTIN').setValue(gstin );
}
, {emitEvent: false}));
}
html will be
<custom-input [autocomplete]="false" [type]="'text'" [autocapitalize]="true"
(focusout)="onChangeGSTIN($event)"
[maxlength]="15" [formControl]="GSTIN"
></custom-input>
I am trying to check the email validity (when the user start typing onkeyup), then if the email is valid I push it into an array of unique emails; however, I stop pushing to the array once it reaches a certain number, in my case it's 3.
<textarea (ngModelChange)="onKeyUp($event)"></textarea>
onKeyUp(ev) {
let finalEmailList = []
this.finalEmailList = [];
this.numberOfUsers = 3;
let emails = ev.replace(' ', '').split(/,| /);
emails.forEach(email => {
if (this.validateEmail(email)) {
//If the email has a valid format, the push it to the array
finalEmailList.push(email);
//it's a lodash function to clean the array an keep only unique emails in the array
this.finalEmailList = _.uniq(finalEmailList);
if (this.finalEmailList.length <= this.numberOfUsers) {
this.numberOfUsers -= this.finalEmailList.length;
}
}
})
}
//returns true if the email has a valid format
validateEmail(email) {
var re = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
The issue:
I believe it's a wrong way to do it as on each and every letter printed from the keyboard everything runs again and again, resetting variables, running for loops, etc...
Also the value returned for this.numberOfUsers is not correct.
If you want the email address to be complete before validating, validating onBlur as others have suggested may be your best course of action.
Another option is to continue listening for onKeyUp, but only trigger validation if the key is a specific trigger key.
Example:
onKeyUp(event) {
if ([13, 188].includes(event.keyCode)) {
validateEmails()
}
}
In this example, 13 and 188 are the key codes for Enter and comma, respectively.
If you want to apply a check on different entries, the simplest solution would be to have one input per email. Not sure it'll fit your need as you haven't say whether you want to stick with a textarea or not but here's my idea:
Create a form containing a formArray with all the required emails.
this.emailsForm = this.fb.group({
emails: this.fb.array(this.getEmailsFormGroup())
});
Here's how to create the formArray:
getEmailsFormGroup() {
const emailsForms: FormGroup[] = [];
for (let i=0; i<this.nbEmails; i++) {
emailsForms.push(this.fb.group({
email: ['', [emailValidator()], []]
}));
}
return emailsForms;
}
Here we're taking advantage of the validators array and calling a custom validator emailValidator, which is defined like that:
const emailRegex = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
export function emailValidator(): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
return emailRegex.test(control.value) ?
null :
{ 'not-email-like': { value: control.value } };
};
}
Full component code (TS):
#Component({
selector: 'app-emails',
templateUrl: './emails.component.html',
styleUrls: ['./emails.component.css']
})
export class EmailsComponent implements OnInit {
nbEmails = 3;
emailsForm: FormGroup;
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.emailsForm = this.fb.group({
emails: this.fb.array(this.getEmailsFormGroup())
});
}
getEmailsFormGroup() {
const emailsForms: FormGroup[] = [];
for (let i = 0; i < this.nbEmails; i++) {
emailsForms.push(this.fb.group({
email: ['email-' + i, [emailValidator()], []]
}));
}
return emailsForms;
}
}
HTML:
Please enter the {{ nbEmails }} required email{{ nbEmails > 1 ? 's' : '' }}
<form [formGroup]="emailsForm">
<div formArrayName="emails">
<div *ngFor="let email of emailsForm.controls['emails'].controls; let i=index" [formGroupName]="i">
<input
type="text"
formControlName="email"
>
</div>
</div>
</form>
<hr>
<div>
VALID? {{ emailsForm.valid }}
</div>
<hr>
<div>
<pre>
{{ emailsForm.value | json }}
</pre>
</div>
Here's a working version on Stackblitz:
https://stackblitz.com/edit/angular-lxltri?file=src%2Fapp%2Femails%2Femails.component.ts
Notice that you have access to the property valid of the form so you know when the X emails are in a valid state.
What I understand is, you have a textarea, where user can enter multiple emailIds. You want to validate each and add into an array.
First, you should not subscribe to ngModelChange, instead subscribe to blur event. Which means only when user moves out of the field, you split the input value based on comma separator and validate each.
Second, you can also separate the input value based on /n i.e. line change. using this .split(/\r?\n/)
This way you don't have to clean array, loop through input field value every time user enters something.
I rather have a single input and a add button. Take the email input and run the logic on click event of add button.That will make sure code runs only when needed and provides user with a better UX. Something like git has done with user profiles
Reference UI
I am doing a form for my javascript class, and I am getting stuck on a certain portion of it. I have a separate validator javascript file and call the function on the html file. All the validation works if the form areas are not filled in. What I want to do is if the fields are left blank they will fail the validation and will insert a value into that field. Below are an example of the form field, javascript function in the html page, and the external validator js file.
call function in html head:
function formvalidation(thisform) {
with (thisform) {
if (textbox_validation(first_name,"Please enter your first name.")==false)
{first_name.blur(); return false;};
if (textbox_validation(business_name,"Please enter your business. Please enter N/A if
you do not have one.")==false) { business_name.focus(); return false;
business_name.value=="N/A";};
The external js validator:
function textbox_validation(entered, alertbox) {
with (entered) {
if (value==null || value=="") {
alert(alertbox);
return false;
}
else {
return true;
}
}
}
So the validator works and focuses on the empty fields, but for some of my fields I want them to fill themselves with a certain value if validation fails or if it isnt filled int. The business_name line of code is when I tried to make it work. Any help is much appreciated!
Ordinarilly, you wouldn't use alert, but would instead put error messages in a span or div either near the input or at the top (or bottom) of the form. Additionally (as mentioned by #Frits van Campen) it is generally bad practice to use with
Try something like this instead:
function textbox_validation(entered, errormsg) {
var errbox = document.getElementById(entered.id + '-errors'); // just to prevent writing it twice
// Note this requires the input to have an id, and the errer box's id to be the same with an '-errors' suffix.
// Instead of using with, just acces properties normally
if (!entered.value) { // The `!` "neggation" operater makes "falsy" values `true`
// "falsy" values include `false`, the empty string, `0`, `null`, `undefined`, `NaN` and a few others
// Put the error message in the DOM instead of alerting it
errbox.innerHTML = errormsg;
return false;
}
else {
// Wipe any previous error messages
errbox.innerHTML = '';
return true;
}
}
And for the form validator, again; let's not use with. But also, when attempting to assing "N/A" to the value, you've used the comparison operator instead of the assignment operator, and you've done it after returning:
function formvalidation(thisform) {
// just use the `!` "negation" operator
if (!textbox_validation(thisform.first_name,
"Please enter your first name."))
{
thisform.first_name.blur();
return false;
}
if (!textbox_validation(business_name,
"Please enter your business. Please enter N/A if you do not have one."))
{
thisform.business_name.focus();
thisform.business_name.value = "N/A"; // for assignment, use `=`. `==` and `===` are used for comparison
return false; // a return statement ends the function, make sure it's after anything you want to execute!
}
}
Use the DOM to set the placeholder for the fields. Like this.
var myInput = document.getElementById('input1');
myInput.placeholder = 'This validation has failed.';
I've got two input fields, email and email_confirm. The email field has the value of the users email from the database. I want to make sure if the user updates their email (both inputs have to have the same value) that they match, however, I can't use the defaul equalTo because email input always has a value. So I need to check if email_confirm is equalTo email IF the email value is different to the default value.
Here's the code I have, value seems to be empty always also.
$.validator.addMethod('myEqual', function (value, element, param){
return value == $(param).val();
}, 'Message');
Just add the below rule for email_confirm field,
equalTo : "#email" //Replace #email with the id the of the email field.
No need to add custom method for that.
if ($("#email").val() != theDefaultValue) {
if ($("#email").val() == $("#email_confirm")) {
// It's all good
} else {
// It's all bad
}
} else {
// It doesn't matter
}