Regex input formatting with vue.js - regex

I'm trying to format user input in vue.js. The input is representing time mm.ss. Two numbers then dot and two numbers again. The dot should appear automatically after first two number are typed. I was able to achieve it using rexeg here's the codepen:
https://codepen.io/Marek92/pen/KKKqKjx
<div id="app">
<h1>{{ title }}</h1>
<input type="text" v-model="performance">
</div>
new Vue({
el: '#app',
data: {
title: 'Input formating!',
performance: '12.00'
},
watch: {
performance() {
this.performance = this.performance.replace(/[^0-9]/g, '')
.replace(/^(\d{2})(\d{2})?/g, '$1.$2')
.substr(0, 5);
}
}
});
However the problem is when the input is there. Let's say '12.00' and you start deleting the number using backspace from the end. You get stuck on the dot. Unable to delete the dot and that is my problem. How can I change the regex to be able delete the dot? Or some other solution?

Please look at below code-
new Vue({
el: '#app',
data: {
title: 'Input formating!',
performance: '12.00'
},
watch: {
performance() {
var a = this.performance.replace(/[^0-9]/g, '')
.substr(0, 5);
if (a.length >= 3) {
a = a.substring(0, 2) + '.' + a.substring(2, a.length)
}
this.performance =a;
}
}
});
Explanation: Try to add a point after 2 digit when there is more than 2 digits. otherwise remove all characters except digits.
https://codepen.io/ashfaq_haq/pen/xxxrbYO

I had ESLint build rules in place that were not allow me to use Regex. If you have the same issue simply removed the rules by configuring the eslintrc.js file
'rules': {
// allow regex test of phone numbers
'no-useless-escape': 0
}
and then you can create the const and use the test method. worked great for my phone number check.
const phoneNumberFormat =
new RegExp(/^[+]?(\d{1,2})?[\s.-]?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/)
const validatePhoneNumber = (context, event) => {
let address = context.address
if (!phoneNumberFormat.test(address.phoneNumber)) {
return false
}
return true
}

Your second capture group is optional, so it will try to add the . when you delete it because a two digit number also matches the regex. One option is to remove the optional syntax ?, use /^(\d{2})(\d{2})/g or /^(\d{2})(\d{1,2})/g so that it only starts to format when there are more than two numbers.
See https://codepen.io/leopsidom/pen/zYYzxKY.

Related

Regex for the first 3 digits in a 6 digit number

I have items in a cms which have a 6-digit number.
The user can filter these item, via a input field,
by start typing a number.
const list = document.querySelector('#filter-wrap');
const searchBar = document.forms['search-kelim'].querySelector('input');
searchBar.addEventListener('keyup', function(e){
const term = e.target.value.toLowerCase();
const kelims = list.getElementsByClassName('filter-item');
Array.from(kelims).forEach(function(kelim){
let number = kelim.firstElementChild.textContent;
if(number.toLowerCase().indexOf(term) != -1 ){
console.log("Valid");
} else {
console.log("Invalid");
}
});
});
This is working, but it filters no matter where the digit
is occurring within the 6-digit number.
Aim is, it should only filter the first 3 starting digits, already starting with the first digit.
Meaning, if the user types 2, only the items starting with 2 are shown,
if the user then types 1, only the items starting with 21 are shown.
(the same for the third digit, typing 214 matches only the items starting with 214)
instead of indexof i tried with regex, but cannot get it to work:
var re = new RegExp("^[0-9]+$");
if (re.test(term)) {
console.log("Valid");
} else {
console.log("Invalid");
}
also tried these regex:
var re = new RegExp("^[0-9]");
var re = new RegExp("^\d{3}[0-9]");
var re = new RegExp("/[0-9]{1}[0-9]{1}[0-9]{1}/");
i also tried with match but also no luck, (different syntax?)
UPDATE:
here are two codepens for better understanding:
Filter with indexof, working but for first 3 digits.
https://codepen.io/hhentschel/pen/LYNWKeK
Filter with Regex, i tried all different answers, which came up so far.
https://codepen.io/hhentschel/pen/yLOMmbw
Your number variables all start with a line break. You may easily check that if you add console.log("'"+number+"': number") in the code.
To fix the regex approach, you just need to trim the incoming strings:
var re = new RegExp("^"+term);
if (re.test(number.trim())) { // <-- HERE!
kelim.classList.add("block");
kelim.classList.remove("hide");
} else {
kelim.classList.add("hide");
kelim.classList.remove("block");
}
Just check whether the Index is 0:
if(number.toLowerCase().indexOf(term) == 0){
console.log("Valid");
} else {
console.log("Invalid");
}
So you know that the term is at the beginning of the number.
But if you want to use regex, you have to build a new pattern every time:
var re = new RegExp("^"+term);
if (re.test(number)) {
console.log("Valid");
} else {
console.log("Invalid");
}

How to assert that a text ends with digits in protractor

I would like to assert in Protractor that a link text is composed by the following way: text-1 (where text is a variable, and the number can be composed by any digits).
I tried the following:
browser.wait(
ExpectedConditions.visibilityOf(
element(by.xpath(`//a[#class = 'collapsed' and starts-with(text(), '${text}') and ends-with(text(), '-(/d+)')]`))),
5000)
and
browser.wait(
ExpectedConditions.visibilityOf(
element(by.xpath(`//a[#class = 'collapsed' and starts-with(text(), '${text}') and ends-with(text(), '/^-(/d+)$/')]`))),
5000)
Unfortunately, none of the above xpaths worked.
How can I fix this?
If you change the way to declare the variable and your second predicate you can go with :
//a[#class='collapsed'][starts-with(text(),'" + text_variable + "')][number(replace(.,'^.*-(\d+)$','$1'))*0=0]
where [number(replace(.,'^.*-(\d+)$','$1'))*0=0] test for the presence of a number at the end of a string.
Example. If you have :
<p>
<a class="collapsed">foofighters-200</a>
<a class="collapsed">foofighters</a>
<a class="collapsed">boofighters-200</a>
<a class="collapsed">boofighters-200abc</a>
</p>
The following XPath :
//a[#class='collapsed'][starts-with(text(),'foo')][number(replace(.,'^.*-(\d+)$','$1'))*0=0]
will output 1 element :
<a class="collapsed">foofighters-200</a>
So in Protractor you could have :
var text = "foo";
browser.wait(ExpectedConditions.visibilityOf(element(by.xpath("//a[#class='collapsed'][starts-with(text(),'" + text + "')][number(replace(.,'^.*-(\d+)$','$1'))*0=0]"))), 5000);
...
You can use regexp for this:
await browser.wait(async () => {
return new RegExp('^.*(\d+)').test(await $('a.collapsed').getText());
}, 20000, 'Expected link text to contain number at the end');
Tune this regex here if needed:
https://regex101.com/r/9d9yaJ/1

Angular regex error

I'm creating a form in Angular that requires the rate field to take only numbers with 2 decimal places. My HTML is as follows:
<input type="number" class="form-control" (keypress)="_keyPress($event)" (ngModelChange)="Valuechange($event,salesorder,'Rate')" [ngModelOptions]="{standalone: true}" name="customerCode" #customerCode="ngModel" [(ngModel)]="salesorder._dto.rate" [style]="{'text-align':'right'}" />
On every keypress event I'm calling _keyPress() method as follows:
_keyPress(event: any) {
const pattern = /[0-9\+\.\ ]/;
let inputChar = String.fromCharCode(event.charCode);
if (!pattern.test(inputChar)) {
// invalid character, prevent input
event.preventDefault();
}
}
The above regex works fine but does not restrict the number to 2 decimal places. I tried with various regex but could not implement the restriction to 2 decimal places. The last regex I used to do the same is as follows:
const pattern = /[0-9]+(.[0-9]{0,2})/;
I have no much idea about regex.
You can try following regex:
const pattern = /^[0-9]*\.[0-9]{2}$/
Or you may use shorthand character class \d instead of [0-9] i.e:
const pattern = /^\d*\.\d{2}$/
Description:
[0-9]{2}$ or \d{2}$ will make sure that there are exactly 2 numbers after decimal point.
You may replace * with + if there must be at least one number before point.
To restrict the decimal place to 2 digits, you could use {2}.
{0,2} means match zero, one or two times.
[0-9]+(\.[0-9]{2})
Note
This uses an unnecessary capturing group (\.[0-9]{2}) which could be written as \.[0-9]{2}
You could also use anchors to match from the beginning ^ to the end $:
^[0-9]+(\.[0-9]{2})$
or
^[0-9]+\.[0-9]{2}$
var pattern = /^[0-9]+(\.[0-9]{2})$/;
var inputs = [
"22.65",
"22.6",
"22.656"
];
for (var i = 0; i< inputs.length; i++) {
console.log(pattern.test(inputs[i]))
}

Regex to validate date yyyy-mm-dd while typing (on keyup)

I need to validade date yyyy-mm-dd on user keyup.
I'm currently at validating yyyy-mm with this Regex
^\d{0,4}$|^\d{4}[-]$|^\d{4}[-](0?[0-9]|1[012])$
JS Fiddle
But I need validade others part of date. Can anyone help me?
Explanation: Vague checking input while typing if it matches the desired format yyyy-mm-dd.
Modified your current regex a bit and added the dd part so it becomes
^\d{0,4}$|^\d{4}-0?$|^\d{4}-(?:0?[1-9]|1[012])(?:-(?:0?[1-9]?|[12]\d|3[01])?)?$
(?: opens a non capture group for alternation
0?[1-9]? optional 1-9 with preceding 0 or zero
[12]\d days 10-29
3[01] days 30 and 31
See the demo at regex101
For dd-mm-yyyy try this variant:
^0?$|^(?:0?[1-9]|[12]\d|3[01])(?:-(?:(?:0$|0?[1-9]|1[012]?)(?:-\d{0,4})?)?)?$
Or for mm-dd-yyyy that one:
^0?$|^(?:0?[1-9]|1[012]?)(?:-(?:(?:0$|0?[1-9]|[12]\d|3[01])(?:-\d{0,4})?)?)?$
This does not actually validate a date (leap years/28-31 days). Just loose checks input while typing, you can probably make it shorter. As follows an example with the yyyy-mm-dd pattern.
$("#date").on("keyup", function()
{
let valid = /^\d{0,4}$|^\d{4}-0?$|^\d{4}-(?:0?[1-9]|1[012])(?:-(?:0?[1-9]?|[12]\d|3[01])?)?$/.test(this.value), input = this.value;
if(!valid) {
this.value = input.substring(0, input.length - 1);
this.style.backgroundColor = '#EEA39C';
}
setTimeout(() => { this.style.backgroundColor = '#88DD85'; }, 700);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="date" style="font-size: 20px" maxlength="10" type="text" />
To validate the full date when typed/submitted see this answer of #PhiLho and rearrange it to the desired format, e.g. for yyyy-mm-dd
function isValidDate(date)
{
var matches = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(date);
if (matches == null) return false;
var y = matches[1];
var m = matches[2] - 1;
var d = matches[3];
var composedDate = new Date(y, m, d);
return composedDate.getDate() == d &&
composedDate.getMonth() == m &&
composedDate.getFullYear() == y;
}
<input type="text" id="date" style="font-size: 17px" value="2016-03-16">
<button onclick="alert(
isValidDate(getElementById('date').value)
);" style="font-size: 17px">check date</button>
This regex is a bit complex, but check the whole Gregorian rule.
regExp = "(((\d{2}(([13579][26])|([2468][480])|(0[48])))|(([13579][26])|([02468][480]))00)-02-29)|(\d{4}-((?:(0[13578]|1[02])-([0-2]\d|3[0-1]))|(?:(0[469]|11)-([0-2]\d|30))|(?:02-([0-1]\d|2[0-8]))))"
var regExp = /^(\d{4})-(\d{2})-(\d{2})$/
regExp.test(value);

Regex is showing phone number as valid for 9 & 10 total digits when it should show valid for 10 digits only

I am using this to validate the phone number.....It shouldbe of 10 digits and once its of 10 digits, remove the red squiggly line and format it in (xxx)xxx-xxxx in this pattern. But, according to this validation, when I am finished writing 9 digits, it shows the number as valid number and removes the red squiggly line and then when I write the 10th digit, it formats in the above pattern.
// custom Vtype for vtype:'phone'
// Vtype for phone number validation
Ext.apply(Ext.form.VTypes, {
'phoneText': i18n.validation.phonetext,
'phoneMask': /[\-\+0-9\(\)\s\.Ext]/,
'phoneRe': /^(\({1}[0-9]{3}\){1}\s{1})([0-9]{3}[-]{1}[0-9]{4})$|^(((\+44)? ?(\(0\))? ?)|(0))( ?[0-9]{3,4}){3}$|^Ext. [0-9]+$/,
'phone': function (v) {
return this.phoneRe.test(v);
}
});
// Function to format a phone number
Ext.apply(Ext.util.Format, {
phoneNumber: function(value) {
var phoneNumber = value.replace(/\./g, '').replace(/-/g, '').replace(/[^0-9]/g, '');
if (phoneNumber != '' && phoneNumber.length == 10) {
return '(' + phoneNumber.substr(0, 3) + ') ' + phoneNumber.substr(3, 3) + '-' + phoneNumber.substr(6, 4);
} else {
return value;
}
}
});
Ext.namespace('Ext.ux.plugin');
// Plugin to format a phone number on value change
Ext.ux.plugin.FormatPhoneNumber = Ext.extend(Ext.form.TextField, {
init: function(c) {
debugger;
c.on('change', this.onChange, this);
},
onChange: function(c) {
debugger;
c.setValue(Ext.util.Format.phoneNumber(c.getValue()));
}});
this.phone = {
xtype: 'textfield',
country: Bedbath.registry.params.country,
labelSeparator: "",
fieldLabel: i18n.label.phone+": <span style='color:red'>*</span>",
name: "phone1RE",
ref: 'phone1RE',
id: 'phone1RE',
allowBlank: false,
vtype:'phone',
plugins: new Ext.ux.plugin.FormatPhoneNumber()
};
I dont know how its showing it as valid for 9 digits? Can someone help me out? Thank you.
Your middle option allows for 9 digits.
^(((\+44)? ?(\(0\))? ?)|(0))( ?[0-9]{3,4}){3}$
everything is optional except the last part, which can be 3-4 numbers repeated 4 times (this is 9-12 digits)
If you want to make sure it's 10 characters and you are using US type numbers (which it appears you are), then this would work to make 10 numbers with a possible space between the correct spots, you could change the last part to something like:
((?: ?[0-9]{3}){2} ?[0-9]{4})
In total it would be like this:
^(\({1}[0-9]{3}\){1}\s{1})([0-9]{3}[-]{1}[0-9]{4})$|^(((\+44)? ?(\(0\))? ?)|(0))((?: ?[0-9]{3}){2} ?[0-9]{4})$|^Ext. [0-9]+$
Debuggex Demo