Je veux utiliser une entrée numérique formatée pour montrer mille points de séparation à l'utilisateur lorsqu'il tape de grands nombres. Voici le code de directive que j'ai utilisé: http://jsfiddle.net/LCZfd/3/
Lorsque j'utilise input type="text"
ça marche, mais quand je veux utiliser input type="number"
il est bizarrement nettoyé par quelque chose lorsque l'utilisateur tape de grands nombres.
Quel est le problème au sujet de input[number]
?
Comme indiqué dans les commentaires, input type="number"
Ne prend en charge que des chiffres, un séparateur décimal (généralement ,
Ou .
, Selon les paramètres régionaux) et -
ou e
. Vous pouvez toujours saisir ce que vous voulez, mais le navigateur supprimera tout caractère inconnu/incorrect.
Cela vous laisse 2 options:
type="text"
et la validation de modèle comme pattern="[0-9]+([\.,][0-9]+)*"
pour limiter ce que l'utilisateur peut entrer tout en formatant automatiquement la valeur comme vous le faites dans votre exempletype="number"
, comme illustré iciCette dernière solution utilise une balise <label>
Supplémentaire qui contient la valeur actuelle et est masquée via CSS lorsque vous concentrez le champ de saisie.
Vous devez ajouter l'attribut step
à votre entrée number
.
<input type="number" step="0.01" />
Cela permettra des virgules flottantes.
Je recommanderais également de revoir le fil de bogue sur les entrées number
dans Firefox. Vous pouvez envisager de ne pas utiliser ce type d'entrée, car il vient juste d'être pris en charge dans ce libération de FF.
Toutes ces années plus tard, il n'y a toujours pas de solution HTML5 prête à l'emploi.
J'utilise <input type="tel">
Ou <input type="text">
("Tel" fait apparaître un clavier numérique dans Android et iOS, ce qui dans certains cas est un bonus.)
Ensuite, j'avais besoin d'une directive pour:
$parsers
et keyup
pour régler elem.val()
et $formatters
pour régler l'affichage ...ng-model
un nombre à virgule flottanteL'exemple de directive ci-dessous le fait et accepte les nombres négatifs et à virgule flottante, sauf si vous spécifiez que vous ne voulez que des nombres positifs ou entiers.
Ce n'est pas la solution complète que j'aimerais, mais je pense que cela comble le fossé.
HTML
<input type="text" ng-model="someNumber" number-input />
JAVASCRIPT
myApp.directive('numberInput', function($filter) {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ngModelCtrl) {
ngModelCtrl.$formatters.Push(function(modelValue) {
return setDisplayNumber(modelValue, true);
});
// it's best to change the displayed text using elem.val() rather than
// ngModelCtrl.$setViewValue because the latter will re-trigger the parser
// and not necessarily in the correct order with the changed value last.
// see http://radify.io/blog/understanding-ngmodelcontroller-by-example-part-1/
// for an explanation of how ngModelCtrl works.
ngModelCtrl.$parsers.Push(function(viewValue) {
setDisplayNumber(viewValue);
return setModelNumber(viewValue);
});
// occasionally the parser chain doesn't run (when the user repeatedly
// types the same non-numeric character)
// for these cases, clean up again half a second later using "keyup"
// (the parser runs much sooner than keyup, so it's better UX to also do it within parser
// to give the feeling that the comma is added as they type)
elem.bind('keyup focus', function() {
setDisplayNumber(elem.val());
});
function setDisplayNumber(val, formatter) {
var valStr, displayValue;
if (typeof val === 'undefined') {
return 0;
}
valStr = val.toString();
displayValue = valStr.replace(/,/g, '').replace(/[A-Za-z]/g, '');
displayValue = parseFloat(displayValue);
displayValue = (!isNaN(displayValue)) ? displayValue.toString() : '';
// handle leading character -/0
if (valStr.length === 1 && valStr[0] === '-') {
displayValue = valStr[0];
} else if (valStr.length === 1 && valStr[0] === '0') {
displayValue = '';
} else {
displayValue = $filter('number')(displayValue);
}
// handle decimal
if (!attrs.integer) {
if (displayValue.indexOf('.') === -1) {
if (valStr.slice(-1) === '.') {
displayValue += '.';
} else if (valStr.slice(-2) === '.0') {
displayValue += '.0';
} else if (valStr.slice(-3) === '.00') {
displayValue += '.00';
}
} // handle last character 0 after decimal and another number
else {
if (valStr.slice(-1) === '0') {
displayValue += '0';
}
}
}
if (attrs.positive && displayValue[0] === '-') {
displayValue = displayValue.substring(1);
}
if (typeof formatter !== 'undefined') {
return (displayValue === '') ? 0 : displayValue;
} else {
elem.val((displayValue === '0') ? '' : displayValue);
}
}
function setModelNumber(val) {
var modelNum = val.toString().replace(/,/g, '').replace(/[A-Za-z]/g, '');
modelNum = parseFloat(modelNum);
modelNum = (!isNaN(modelNum)) ? modelNum : 0;
if (modelNum.toString().indexOf('.') !== -1) {
modelNum = Math.round((modelNum + 0.00001) * 100) / 100;
}
if (attrs.positive) {
modelNum = Math.abs(modelNum);
}
return modelNum;
}
}
};
});
vous pouvez essayer cela, j'ai modifié la directive que j'ai vue ici ... Comment puis-je restreindre une entrée pour n'accepter que des nombres? ...
voici la directive modifiée que j'ai faite ... Cette directive utilise l'événement keyup pour modifier l'entrée à la volée ...
.directive('numericOnly', function($filter) {
return {
require: 'ngModel',
link: function(scope, element, attrs, modelCtrl) {
element.bind('keyup', function (inputValue, e) {
var strinput = modelCtrl.$$rawModelValue;
//filter user input
var transformedInput = strinput ? strinput.replace(/[^,\d.-]/g,'') : null;
//remove trailing 0
if(transformedInput.charAt(0) <= '0'){
transformedInput = null;
modelCtrl.$setViewValue(transformedInput);
modelCtrl.$render();
}else{
var decimalSplit = transformedInput.split(".")
var intPart = decimalSplit[0];
var decPart = decimalSplit[1];
//remove previously formated number
intPart = intPart.replace(/,/g, "");
//split whole number into array of 3 digits
if(intPart.length > 3){
var intDiv = Math.floor(intPart.length / 3);
var strfraction = [];
var i = intDiv,
j = 3;
while(intDiv > 0){
strfraction[intDiv] = intPart.slice(intPart.length-j,intPart.length - (j - 3));
j=j+3;
intDiv--;
}
var k = j-3;
if((intPart.length-k) > 0){
strfraction[0] = intPart.slice(0,intPart.length-k);
}
}
//join arrays
if(strfraction == undefined){ return;}
var currencyformat = strfraction.join(',');
//check for leading comma
if(currencyformat.charAt(0)==','){
currencyformat = currencyformat.slice(1);
}
if(decPart == undefined){
modelCtrl.$setViewValue(currencyformat);
modelCtrl.$render();
return;
}else{
currencyformat = currencyformat + "." + decPart.slice(0,2);
modelCtrl.$setViewValue(currencyformat);
modelCtrl.$render();
}
}
});
}
};
vous l'utilisez comme ça ...
<input type="text" ng-model="amountallocated" id="amountallocated" numeric-only />
Vous ne pouvez pas utiliser de valeurs avec ,
car type=number
ne prend que des nombres, l'ajout d'une virgule en fait une chaîne.
Voir http://jsfiddle.net/LCZfd/5
Vous feriez mieux de faire vos propres contrôles si vous voulez des virgules. Un avec une vraie valeur (le nombre) et une valeur d'affichage (la chaîne).