Cannot access this when ng-keyup is called the second time - javascript

There is an input field like:
<input ng-if="$ctrl.inputType === 'input'"
name={{$ctrl.param.Name}}
type="text"
ng-keyup="$ctrl.keyp()"
..."
/>
and the keyp() function in controller:
class AlertParameterCtrl {
constructor(AlertParameterService, $element){
this.AlertParameterService = AlertParameterService;
this.$element = $element;
this.overrideText = 'Override default';
this.inputType = 'input';
this.unitlessParameter = false;
}
...
keyp() {
const dec = 2;
const regex = new RegExp("(\\.\\d{" + dec + "})\\d+", "g");
this.param.value = this.param.value.replace(regex, '$1');
}
}
AlertParameterCtrl.$inject = ['AlertParameterService', '$element'];
The aim is to make possible to introduce maximum of 2 digits after the decimal point.
I had put a debbuger inside keyp() to see how it is behaving. When there is added a new digit after the decimal, the value of this.param.value remains on step before.
For example, if the inital value is 100 and I write 100., the value of this.param.value remains 100.
After this step, I introduce another digit, 100.2, the value of this.param.value becomes 100. and so on.
So, when there are 3 digits in the input and 2 digits in the variable (this.param.value), I'm writing another one to see if it will stop it from putting it in the input form.
But instead of using the regex for doing so, the value of this.param.value is undefined and I'm receiving this error:
Cannot read property 'replace' of undefined
Does anybody know why are these 2 problems occur? Like being on step before and why when the 3rd digit is introduced the variable storing it is undefined?

Related

How to prevent the input field from accepting more than 2 decimal places in react native?

Restrict input field from accepting more than 2 decimal places. In most of the places, This is recommended, But instead of validating later, I dont want to allow more than 2 decimal places in the input field itself.
var validate = function(e) {
var t = e.value;
e.value = (t.indexOf(".") >= 0) ? (t.substr(0, t.indexOf(".")) + t.substr(t.indexOf("."), 3)) : t;
}
</script>
</head>
<body>
<p> Enter the number</p>
<input type="text" id="resultText" oninput="validate(this)" />
You could try this.
Set up your state for the input: const [value, setValue] = useState()
Then in your TextInput callback onChangeText, set it up like this.
onChangeText={(text) => {
const validated = text.match(/^(\d*\.{0,1}\d{0,2}$)/)
if (validated) {
setValue(text)
}
}}
This validates a string first to match the following pattern:
zero or more digits
followed by 0 or 1 decimal place
followed by 0, 1, or 2 decimal places (but no more than 2)
I also start the regex with a ^ which forces the match to start at the beginning of the text.
The text argument that is passed in to onChangeText is the entire string (not just the next character). If this string doesn't conform to the regex we set up (validation) then we ignore this value and the state isn't updated.
I'm sure there are other ways to do this, but this one worked for me.
Let me also add this: in React Native's TextInput you can control the keyboard type. Mine is set to a numeric keyboard so the user never gets a chance to enter a letter. This should work either way. It's just a side note
<input pattern='d\+\.\d\d$'/>
You can specify a regex pattern on the input and tell it to only accept numbers (\d), along with a dot and only two numbers after the dot.
I have no idea if that works in react native, only in browsers.
You don't necessarily have to resort to regex.
You can simply use conditionals of substrings on top of regex.
const onChangeText = (text) => {
// Only allow "number & ." input
const cleanNumber = text.replace(/[^0-9.]/g, "")
// Only take first 2 values from split. Ignore the rest.
const strAfterDot = cleanNumber.split('.', 2)[1]
if (strAfterDot.length <= 2){
console.log("setValue now")
setValue(text)
} else {
console.log("Should not be allowed. You can trim the value yourself.)
const strBeforeDot = cleanNumber.split('.', 1)[0]
setValue(strBeforeDot + '.' + strAfterDot.substr(0, 2))
}
}
(Not tested for edge-cases, I'll leave that up to you.)

Text Input Real time JS validation as Float which accepts floating point and comma

I want to validate an input in real time way.
The input has type text and must validate only an input having : number(s) and/or floating point or comma.
Also the input accepts only two numbers after the floating point/comma.
Examples :
- 12.23 Valid
- 12,23 Valid
- 12.2 Valid
- 12,02 Valid
- 2 Valid
- 12.035 Invalid
- 12.36E Invalid
- test Invalid
I suggest tracking the live input validation with a /^(\d*)([,.]\d{0,2})?$/ regex that allows typing any 0 or more digits at the start, and then an optional substring of , or . and then 0, 1 or 2 digits. If there is a match, re-format the value by replacing , with .. If there input value is not matched, replace it with the last good value (say, introduce a variable called prevValue for that).
Once you want to submit this value, you need to make sure the value is in the final format, that is, there should be no . at the end. To enable this, add a pattern attribute to your <input> and assign the ^\d+(?:\.\d{1,2})?$ regex to it. Here, it will already require 1+ digits at the start of the string, and then will match an optional substring of a . followed with 1 or 2 digits. See the regex demo. Since the comma will get replaced with a dot, you need no [.,] pattern, \. is enough.
Also, it is a good idea to handle the input value change on paste.
var prevValue = "";
var patt = /^(\d*)([,.]\d{0,2})?$/;
function validateCurrencyPattern(price){
var matchedString = price.match(patt);
if (matchedString) {
prevValue = matchedString[1] + (matchedString[2] ? matchedString[2].replace(",", ".") : "")
return prevValue;
}
else {
return prevValue;
}
}
$(document).on("keypress keyup blur paste","#field", function (event) {
$(this).val(validateCurrencyPattern($(this).val()));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<input type="text" id="field" name="field" pattern="^\d+(?:\.\d{1,2})?$"/>
<input type="Submit"/>
</form>
Since I did not find the solution on stack and spent some hours to develop a solution that can help others i'll share what i've done :
I used the RegExp pattern to validate the number.but i can't do it with one pattern so i've created two patterns.
The first validates: x*.yy
And the second validates: x*,yy
Constraints : isNumeric doesn't accept float with comma.so that's why i've converted it.
The function validation function code :
and The call for function mixing the events (keypress keyup blur)
function validateCurrencyPattern(price){
var patt = new RegExp(/[0-9]+[.]{1}[0-9]{2}/i);
var convertedPrice =price.replace(',', '.');
var matchedString = price.match(patt) ;
var matchedString2 = convertedPrice.match(patt) ;
if (matchedString) {
return matchedString
}
if (matchedString2) {
return matchedString2
}
if((!$.isNumeric(convertedPrice))|| convertedPrice<0){
return null;
}
else if(!matchedString && !matchedString2){
return convertedPrice;
}
}
$(document).on("keypress keyup blur","#field", function (event) {
$(this).val(validateCurrencyPattern($(this).val()));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="field" name="field">
Feel Free to optimize this solution or suggest another alternative that may be better than the existing solution.

JavaScript regex: capturing optional groups while having a strict matching

I am trying to extract some data from user input that should follow this format: 1d 5h 30m, which means the user is entering an amount of time of 1 day, 5 hours and 30 minutes.
I am trying to extract the value of each part of the input. However, each group is optional, meaning that 2h 20m is a valid input.
I am trying to be flexible in the input (in the sense that not all parts need to be input) but at the same time I don't watch my regex to match some random imput like asdfasdf20m. This one should be rejected (no match).
So first I am getting rid of any separator the user might have used (their input can look like 4h, 10m and that's ok):
input = input.replace(/[\s.,;_|#-]+/g, '');
Then I am capturing each part, which I indicate as optional using ?:
var match = /^((\d+)d)?((\d+)h)?((\d+)m)?$/.exec(input);
It is kind of messy capturing an entire group including the letter when I only want the actual value, but I cannot say that cluster is optional without wrapping it with parentheses right?
Then, when an empty group is captured its value in match is undefined. Is there any function to default undefined values to a particular value? For example, 0 would be handy here.
An example where input is "4d, 20h, 55m", and the match result is:
["4d20h55m", "4d", "4", "20h", "20", "55m", "55", index: 0, input: "4d20h55m"]
My main issues are:
How can I indicate a group as optional but avoid capturing it?
How can I deal with input that can potentially match, like abcdefg6d8m?
How can I deal with an altered order? For example, the user could input 20m 10h.
When I'm asking "how to deal with x" I mean I'd like to be able to reject those matches.
As variant:
HTML:
<input type="text">
<button>Check</button>
<div id="res"></div>
JS:
var r = [];
document.querySelector('button').addEventListener('click', function(){
var v = document.querySelector('input').value;
v.replace(/(\d+d)|(\d+h)|(\d+m)/ig, replacer);
document.querySelector('#res').innerText = r;
}, false);
function trim(s, mask) {
while (~mask.indexOf(s[0])) {
s = s.slice(1);
}
while (~mask.indexOf(s[s.length - 1])) {
s = s.slice(0, -1);
}
return s;
}
function replacer(str){
if(/d$/gi.test(str)){
r[0] = str;
}
else if(/h$/gi.test(str)){
r[1] = str;
}
else if(/m$/gi.test(str)){
r[2] = str;
}
return trim(r.join(', '), ',');
}
See here.

how to get value of an input box in html and do operations on it

I was testing a simple code to:
Get value of an input box
Do Mathematical operations on it...
My Code:
setInterval(function(){var a=document.getElementById("myInputBox").value;var b=a+1;a.value=b;},1000);
I am trying to add 1 to the value of that input box, every 1 second.
For example, if the box has value 1 ,then after 1 second it should become 2,....and so on.....
But it gets joined with the box's value, like 11 instead of 2.
Why is that?
Try with full code & demo:
get value from inputbox is a string, so it can't calculate mathematically. so, at first convert string to numeric by using function parseInt and then calculate and put into box.
setInterval(function() {
var box = document.getElementById("myInputBox");
var r = parseInt(box.value, 10) + 1;
box.value = r;
}, 1000);
<input type="text" id="myInputBox" value="1" />
var b = parseInt(a) + 1;
a is a string, so the + is interpreted as string concatenation by default. To fix, pass a to parseInt because it returns a type integer. Now the + becomes a math operator.
Extra Credit:
var b = parseInt(a, 10) + 1;
For an extra measure of integrity, pass the second (radix) argument, ensuring base 10 is used to determine the return integer value.

How to get jQuery animateNumber to pull value dynamically?

I am trying to implement jQuery animateNumber, and I have it working like the demo just fine. However, I want to modify it so that it pulls the number from the HTML, rather than setting it in the script. I tried the following, but it just shows "NAN." What am I doing wrong?
<div class="stat-title animate-number">$16,309</div>
<script>
$('.animate-number').each(function(){
var value = new Number;
// Grab contents of element and turn it into a number
value = $(this).text();
value = parseInt(value);
// Set the starting text to 0
$(this).text('0');
$(this).animateNumber(
{
number: value,
},
1000
)
});
</script>
ParseInt is failing because of the $ character. Also, the comma is messing with parseInt and giving you the value 16 instead of 16309. After that, the animation seems to be working. Also, you don't necessarily have to replace it with 0 since animateNumber automatically starts from 0. Here's my work so far on JSfiddle:
http://jsfiddle.net/0m9828kn/1
$('.animate-number').each(function(){
var value = $(this).text();
value = value.substring(1, value.length);//Remove $ sign
value = value.replace(/,/g, "");//Remove all commas
value = parseInt(value);
//$(this).text("0"); //This part isn't actually necessary
$(this).animateNumber(
{
number: value
},
1000
)
});
Looks like the problem is that ParseInt is choking on the dollar sign. Then when you remove that, it only reads up to comma and animates to 16. Take them both out, and it works.
value = $(this).text().replace(/[\,\$]/g,'');
But, you'll need to include this option to get your comma back:
var comma_separator_number_step = $.animateNumber.numberStepFactories.separator(',')
$(this).animateNumber(
{
number: value,
numberStep: comma_separator_number_step
},
1000
)
To get your dollar sign back, you could change your html to something like this:
<div>$<span class="stat-title animate-number">16,309</span></div>

Categories

Resources