I am creating a web app in which I have a number in my $scope variable
$scope.total=20;
and I have one textbox
<input type="text" ng-model="amount1" ng-change="amountchange(amount1)" />
and when a user enters 500 in the textbox it should be 700 but instead the answer is coming 755 and when I delete 500 from my textbox it became null.
I just want to add or remove from my textbox what I am doing wrong here
Here is a fiddle created by me for better understanding
this problem is in this line:
$scope.total = parseInt($scope.amount1) + parseInt($scope.total);
you aggregate the value when you enter more input instead of just sowing the result.
what you can do is simple, add this method:
$scope.getTotal=function(){
return parseInt($scope.amount1) + parseInt($scope.total);
}
and replace {{total}} with this: {{getTotal()}}
It happens because of ng-change, each time the value is getting added
On entering 500,
Step1 5 + 200
Step2 50 + 205
Step3 500 + 255
and so it becomes 755. Use ng-blur instead of ng-change
<body data-ng-controller="myController">
<input type="text" ng-model="amount1" ng-blur="amountchange()" />
{{total}}
</body>
DEMO
What happens in your app is actually expected, because you add the current number on each input change.
Changing to ng-blur or setting a timeout before updating the value, using the built-in ng-model-options, which can now be done as of Angular 1.6 (released just yesterday) could be good options.
<input type="text" ng-model="amount1" ng-change="amountchange()" ng-model-options="{'debounce':{'default':300}}" />
or:
<input type="text" ng-model="amount1" ng-blur="amountchange()" />
However, I do not recommend either of them, and here's why:
By not letting the user decide when the data they entered is submitted (e.g.: pressing enter or a submit button) you make it user-unfriendly as well as introduce unwanted behaviour, such as when the user clicks off and on the in the second example, the number will have been added again and again...
Consider using a form and ng-submit instead as it's cleaner, more semantic and also conveys a friendlier way for your users to submit data.
Also here's the solution to your other issue:
$scope.amountchange = function () {
var amount = ($scope.amount1 != '') ? $scope.amount1 : 0;
console.log(amount)
if (amount != NaN) {
$scope.total = parseInt(amount) + parseInt($scope.total);
}
else {
alert("Please enter a number.");
$scope.amount1 = $scope.total;
}
}
To explain: first off you did not make use of any arguments, so you do not need to pass the amount1 model's value into the function in your directive. But that wasn't the problem. The reason why it set it to null is that the empty field doesn't parse to a 0, therefore you have to set it yourself. I saved the value into the variable amount on the function and assigned either the value of $scope.amount or 0 if it happens to be empty.
Related
I am trying to given alert to the user, if user enter more than input variable value.
problem statement:
Max_ava_water = 300
if user enter a 6 also it is showing 'Enter less or Equal values'.
var Max_ava_water = 300
$('#input_rd').keyup(function() {
if ($(this).val() > Max_ava_water) {
console.log("Enter less or Equal values")
$(this).val('');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="value" id="input_rd" />
You're checking on every keyup event, which is too soon — the user could be trying to type 600, which starts with 6, which is less than 100. (Sorry, that comment was when I'd misread your > as <. But the basic idea still applies.)
Instead, check when the field loses focus (blur) or when they try to confirm the value in some other way.
I'd strongly suggest not clearing the field when the value is too low. Instead, let them edit the value (maybe they just missed out a 0 at the end).
const Max_ava_water = 300;
// Using `blur` event
$('#input_rd').on("blur", function() {
// Explicit conversion
const value = this.value ? parseInt(this.value, 10) : NaN;
// Note that `NaN` is never `>` anything
if (value > Max_ava_water) {
console.log("Enter less or Equal values")
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="number" id="input_rd" />
Also note that type="value" is invalid for input fields. You could use type="number" as I did above to trigger the browser's standard handling for number fields, perhaps with min and max to do range checking.
Side note: val returns a string (or undefined if you call it on an empty jQuery set, but you aren't). Your expression relies on > to implicitly convert that to a number. > does do that, but often it's better to do the conversion intentionally, not least because the rules for implicit conversion might not be the rules you want to apply ("" converts to 0, for instance). My answer here describes your various options and their pros and cons.
I have an input field:
<input id="thing" type='number' placeholder='Up to 20 tickets' min='1' max='20' name='tickets'>
And despite the fact that I've listed min and max numbers, it still accepts typing random letters into the field, and such.
I'd like to only allow numbers 1 to 20 to appear in the field upon user input of any kind. How might I do that?
'input' DOM event?
some HTML form magic?
Update Haaa, okay, so dynamically created form inputs don't function like normal inputs. The value fields aren't hooked up to user actions.
Never trust user's input. Limiting values in html input is only for user's convenience. Even if you somehow limited user's ability to change input value directly, he could still press f12 (in Chrome), and manually change values to whatever he wants.
That being said, your code works just fine, and does what you want it to do- it limits user to input just numbers, between 1 and 20. Before doing anything with this data though, you have to validate it on the server, so server will make sure if it's really a number, and it's really between 1 and 20, because as I said- there's no way to prevent user from entering literally anything he wants into inputs.
Using Chrome
document.querySelector( "input" ).addEventListener( "input", function( evt ) {
var v = evt.target.value;
if ( v ) {
console.log( v ); // Only outputs numbers
}
}, false );
<input type="number" value="1" min="1" max="20" name="foo" placeholder="bar">
Behaviour is as expected; nothing but numbers 1-20 are output.
You can use Plain Javascript.
<script>
function handleChange(input) {
if ((input.value < 0) && ((input.value > 20))
return false;
}
</script>
HTMl code
<input type="number" onchange="handleChange(this);" />
Or you can use this
<input type="number" onKeyPress="if(this.value.length>20) return false;" />
I ended up doing this:
var temp = ''
input.addEventListener('input', function (event) {
if (this.value == '') return
if (this.value < 1 || this.value > 20 || this.value.match(/\D/)) return this.value = temp
temp = this.value
}, false)
The input event is the most broad. It captures copy pastes, and all other manner of changing field values.
The check for empty string is important, because if some one has typed 15, and changes their mind, and wants to type 20, they'll need to backspace twice, before typing the 2 and the 0. So, the state of empty is valid.
Anytime the function runs it stores the new value in a temp var, and we apply that immediately if we get input we don't like, because preventDefault() doesn't work with the input event.
I am having trouble getting a filter to work on a number/text input.
<input type="number" class="text-center" ng-model="redeem.redemption.Amount | number: 2">
This throws an error: Expression 'redeem.redemption.Amount | number' is non-assignable
If I remove the filter, it works. I tried applying the same filter to the angular input demos and it works fine (https://docs.angularjs.org/api/ng/filter/number). Only difference I can see is I am binding to a an object on the scope and not a value directly. Is there something easy I am missing here?
I guess that what you are trying to do is to display the "formated value" of what they enter?
Then just remove the filter from the ng-model and in your controller watch the redeem.redemption.Amount and format it when the watch gets triggered. you will also need to set a timeout in order to allow the user to type, otherwise every time that the user hits a number the watch will try to format the number and the user won't be able to type anything.
The code that you have posted will never work because ng-model establishes a 2 way data binding with the property of the scope that you indicate, that's why you can not set filters there, it will only accept a property of the scope, that will be updated and from where it will read the value when it changes. The filter is a function with one input and retrieves a different output, think about it, if you set the filter, then Angularjs won't know where it has to set the changes of of the input.
Something like this:
app.controller('MyCtrl', function($scope,$filter,$timeout) {
$scope.testValue = "0.00";
var myTimeout;
$scope.$watch('testValue', function (newVal, oldVal) {
if (myTimeout) $timeout.cancel(myTimeout);
myTimeout = $timeout(function() {
if($filter('number')(oldVal, 2)!=newVal)
$scope.testValue = $filter('number')($scope.testValue, 2);
}, 500);
});
});
http://plnkr.co/edit/WHhWKdynw0nA4rYoy6ma?p=preview
Try tweaking the delay for the timeout, right now its been set to 500ms.
you cant put filter in ng-model directive.you can do it controller using this:
redeem.redemption.Amount=redeem.redemption.Amount.toFixed(2);
or you can use jquery to prevent keypress two digits after a decimal number like this:
$('.decimal').keypress(function (e) {
var character = String.fromCharCode(e.keyCode)
var newValue = this.value + character;
if (isNaN(newValue) || parseFloat(newValue) * 100 % 1 > 0) {
e.preventDefault();
return false;
}
});
<input type="number" id="decimal" class="text-center" ng-model="redeem.redemption.Amount | number:">
I'm stumbling upon weird case while using angularJs and input type="number". Basically, if I have input with type number and initial value falls outside range defined by min and max, my initial value is simply destroyed.
I've made fiddle to illustrate the problem - http://jsfiddle.net/PK3QH/2/
HTML:
<div ng-controller="MyCtrl">
<input ng-model="bindData.SomeAmount" type="number" required="required" />
<br />
<input ng-model="bindData.SomeAmount" type="number" required="required"
min="2" max="10" />
</div>
Javascript:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.bindData = {
SomeAmount: 1
};
}
As you can see first textbox works without any problems, but the second one simply doesn't display the value. I definitely need value to be preserved while also being validated as number in certain range - so is there any way our this?
I agree this is a bug.
This happens because the formatters are applied first before validators.
The formatter in the case of 'number'
if (attr.min) {
var minValidator = function(value) {
var min = parseFloat(attr.min);
return validate(ctrl, 'min', ctrl.$isEmpty(value) || value >= min, value);
};
ctrl.$parsers.push(minValidator);
**ctrl.$formatters.push(minValidator);**
}
all the $formatters are run first before the validators are run initially...checkout NgModelController.
I wonder if the "first" time when $dirty != true if they applied the formaters based on validity i.e. let the formatters yield if the validation results to false.
In the case of minNumber the formatter should be only a number. Why do we need a formatter for minNumber ?
Raised it https://github.com/angular/angular.js/issues/8264
Until the Angular team fixes this short term solution would be to use your own directive instead of min.
IMHO, this is a bug.
If you remove ng-model attribute, you see the initial value.
If this is NOT a bug, when we type invalid value such as 40, we must not see the entered text as it happend as when initialized. See, it's not consistent.
It only happens for the first time when input directive is initialized.
IMO, Even though, the model value is not value, it should preserve the original value by not setting to blank.
Sorry for not providing solution.
I have a function to limit the number of characters that a user can type into an input field for my game. It works, except that if it goes down by 1 or more in length, the user can still enter 1 or more characters than they should be able to.
I check the inspector, and it even shows maxlength changing correctly. However, for whatever reason, it still lets the user enter in a length equal to the max number of characters that the variable was equal to during the same session. Is it a bug? Any way to get it working correctly?
my_var = 150000; //this var changes often, can go down to 0 or up to 1000000000
function limitNumberOfCharacters() {
x = my_var.toString().length;
$('.my_input_class').attr('maxlength', x);
}
limitNumberOfCharacters(); //this gets called often
EDIT: http://jsfiddle.net/mDw6f/
EDITTTT:
You are using x as a global variable and is probably getting changed from something else in your code. Use var x = my_var.toString().length; (emphasis on var)
Honestly after seeing this code I was afraid there would be many more underlying problems but all I did was add var before the xyz and it works just as you want it to.
Also fixed the issue of the previous bet amount returning to the input field. It now results to a blank field.
Cheers
Real Fiddle Example
Try using this fiddle:
Working Demo
Use the html input like I did in the code, no need to specify the maxlength attribute to it.
<input type="text" class="my_input_class"/>
and the script
my_var = 25; //this var changes often, can go down to 0 or up to 1000000000
function limitNumberOfCharacters() {
x = my_var.toString().length;
$('.my_input_class').attr('maxlength', x);
}
limitNumberOfCharacters();