TLDR; (更新)
<input>
是数字类型,而无需使用type=number
属性设置。
<input>
的{{1}},有一种方法可以吞并所有不会产生有效数字的键输入
type=number
上不会出现垃圾删除请阅读以下原始详细说明
我的问题如下:
我有一个html keyup
元素,我只想接受数字并在移动设备上被识别为数字字段。我还希望吞下无效字符,就像标准<input>
吞咽不允许的字符一样。
我尝试了明显的type=number
,但它有很多缺点。具体来说,它允许使用“ e”,“ +”和“-”(至少在chrome中),但是使用JS可以轻松解决这些问题。真正的问题在于“。”字符,我希望能够输入浮点数,例如'0.10','5.5054',但是不想输入例如'0.10.1'之类的无效字符串。我试图通过仅允许1'来解决此问题。一次,但这失败了,因为type=number
被浏览器按摩了,例如'5。变为'5','5 ..'变为null(!),并且似乎无法获得在输入中键入的原始字符串值。以上意味着检查现有的“。”并采取行动似乎是死路一条...
核心问题:
input.value
的后勤负担?注意:
*我意识到您可以粘贴您想要的任何内容,我认为这种行为是病态的,因此不应被输入预防所覆盖。
更新:
为了澄清起见,我已经尝试了type=number
,keypress
等事件,它们并不足够,因为我想查看当前输入中存在多少个'。,以选择是否允许另一个。此时,浏览器已对keydown
进行了按摩,以删除“。”。我想有条件地允许基于当前输入的'。'字符。
示例:
HTML(为简洁起见,使用角度样式绑定)
input.value
JS
<input type="number" (keydown)="keyDown()">
答案 0 :(得分:15)
是否有一种方法可以指示
<input>
是数字类型,而无需使用type=number
属性设置。 即移动设备识别并显示数字键盘等
使用inputmode="decimal"
代替type="number"
表示移动设备使用数字键盘输入。这样,您可以继续使用type="text"
并根据需要处理输入。
有关更多信息,请参见MDN,并在设备上进行测试。{p3}
答案 1 :(得分:3)
一种略有不同的方法。它允许数字,仅1个句点和退格键。 KeyboardEvent.key
的其余所有ctrl + v
(包括ctrl + c
和10
)将被忽略。但是,如果愿意,可以这样做。
要检查字符是否为event.key
数字之一,我使用Digits[0-9]
,因为它们可以有两个不同的代码:Numpad[0-9]
和event.code
。但是对于期间和退格,我使用const input = document.querySelector("#number_input");
const App = {
isDigit: function(key) {
const digits = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
];
return digits.includes(key);
},
isPeriod: function(code) {
return code === "Period";
},
isBackSpace: function(code) {
return code === "Backspace";
},
handleEvent: function(event) {
const key = event.key;
const code = event.code;
const value = input.value;
if (App.isDigit(key) || App.isPeriod(code) || App.isBackSpace(code)) {
if (App.isPeriod(code) && value.indexOf(key) !== -1) {
event.preventDefault();
}
} else {
event.preventDefault();
}
}
};
input.onkeydown = App.handleEvent
,因为它们只有一个代码。
<input id="number_input" />
const input = document.querySelector("#number_input");
const dummyInput = document.querySelector("#dummy_input")
const App = {
isDigit: function(key) {
const digits = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
];
return digits.includes(key);
},
isPeriod: function(code) {
return code === "Period";
},
isBackSpace: function(code) {
return code === "Backspace";
},
handleEvent: function(event) {
const key = event.key;
const code = event.code;
const dummyValue = dummyInput.value;
if (App.isBackSpace(code)) {
dummyInput.value = dummyValue.substring(0, dummyValue.length - 1)
} else {
if (App.isDigit(key) || App.isPeriod(code)) {
if (App.isPeriod(code) && dummyValue.indexOf(key) !== -1) {
event.preventDefault();
} else {
dummyInput.value += event.key
}
} else {
event.preventDefault();
}
}
}
};
input.onkeydown = App.handleEvent
由于您坚持使用数字输入。首次使用时,您可以使用CSS或Js隐藏虚拟文本输入,并验证其值而不是数字输入。
<input type="number" id="number_input" />
<input type="text" id="dummy_input" />
<input type="number" min="1" id="number_input" />
所有使用input [type =“ number”]的答案都有问题。您可以通过鼠标滚轮/微调器将输入的值更改为负数。要解决此问题,请为输入设置最小值。
onchange
您需要监听const input = document.querySelector("#number_input");
const dummyInput = document.querySelector("#dummy_input")
const App = {
isDigit: function(key) {
const digits = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"
];
return digits.includes(key);
},
isPeriod: function(code) {
return code === "Period";
},
isBackSpace: function(code) {
return code === "Backspace";
},
handleEvent: function(event) {
const key = event.key;
const code = event.code;
const dummyValue = dummyInput.value;
if (App.isBackSpace(code)) {
dummyInput.value = dummyValue.substring(0, dummyValue.length - 1)
} else {
if (App.isDigit(key) || App.isPeriod(code)) {
if (App.isPeriod(code) && dummyValue.indexOf(key) !== -1) {
event.preventDefault();
} else {
dummyInput.value += event.key
}
} else {
event.preventDefault();
}
}
},
handleChange: function(event) {
dummyInput.value = event.target.value
}
};
input.onkeydown = App.handleEvent;
input.onchange = App.handleChange;
事件,然后更改虚拟输入的值。
<input type="number" min="1" id="number_input" />
<input type="text" id="dummy_input" />
paginator
答案 2 :(得分:0)
onkeypress
的特殊功能,并检查是否键入了允许的字符。如果不是,请阻止默认行为。
let special = document.getElementById('special_input');
special.addEventListener("keypress", function(e) {
let dot = 46;
// allowed char: 0-9, .
let allow_char = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, dot];
if (allow_char.indexOf(e.which) !== -1) {
// only 1 dot
if (e.which == 46 && special.value.indexOf('.') !== -1)
e.preventDefault();
} else {
e.preventDefault();
}
});
<input id='special_input'>
答案 3 :(得分:0)
已更新
答案随需求变化而更新。
好吧,我尝试解决另一个问题,那就是粘贴
根据以下代码,您不能粘贴任何内容,只能粘贴数字,如果您尝试粘贴字符串,则输入框将自动变为空:)
let special = document.getElementById('inputField');
special.addEventListener("keypress", function(e) {
let dot = 46;
// allowed char: 0-9, .
let allow_char = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, dot];
if (allow_char.indexOf(e.which) !== -1) {
// only 1 dot
if (e.which == 46 && special.value.indexOf('.') !== -1)
e.preventDefault();
} else {
e.preventDefault();
}
});
function checkString()
{
setTimeout(() => {
var value = document.getElementById("inputField").value;
value = parseInt(value);
if(isNaN(value))
document.getElementById("inputField").value = "";
}, 100);
}
<input type="number" id="inputField" onpaste="checkString()"/>
答案 4 :(得分:0)
通过以下方式检查真实性
value == parseFloat(value)
parseFloat()将捕获第一个小数点并删除所有其他小数点。
使用'=='代替'==='将确保参考值不变。
function keyDown($event: KeyboardEvent) {
const inputField = // obtain reference to input element
const value = inputField.value;
if ( value == parseFloat(value)) { // disallow another . if one is present
// ! input field prunes . so this check isn't sufficient
$event.preventDefault();
return;
}
// This is the crux of the problem e.g.
// type 5. into input field, value === 5
// type 5.. into the input field, value === null
// Since the . char is removed by the input element there's no way to know how many are present!
console.log(value);
}
这是一个类似的测试,您可以在node.js中运行以验证它是否完成了您想要的工作。
function numCheck (value) {
if (value == parseFloat(value)) {
console.log(value)
} else {
console.log('not a number')
}
}
numCheck("5");
numCheck("5.5");
numCheck("5.5.5");
numCheck("A");
答案 5 :(得分:-1)
对于限制,正则表达式是最好的选择。在按键上注册事件监听器
numbersOnly(event) {
const numbers = /^([0-9])$/;
const result = numbers.test(event.key);
return result;
}
如果函数与正则表达式不匹配,则上述函数将吞下字符集
Javascript Regex: validating a double/float
以上链接具有正则表达式,该正则表达式允许使用double / float。希望对您有所帮助:)
答案 6 :(得分:-1)
也许是您问题的间接解决方案。您可以查看validity
属性,以确定输入是否有效。
您可以检查有效性而无需访问该值,如果输入无效,则可能不会返回该值。
HTML:
<input type="number" id="num" step="0.1"/>
JS:
var numField = document.getElementById('num');
numField.addEventListener("keyup", event => {
if(!numField.validity.valid)
{
alert('invalid input');
}
});
一些测试:
34 -> valid
3.4 -> valid
e -> invalid
+4 -> valid
3.4. -> invalid
3.4.. -> invalid
.4 -> valid (evaluates to 0.4)
3e+2 -> valid
1e -> invalid
eee -> invalid
-0.3e+1 -> valid
..32e.. -> invalid
这适用于粘贴和输入值。
更新:
原始问题有点冗长。我正在尝试将其分解并分部分回答。
Input [type =“ number”]仅在有效时允许访问该值,否则返回空。因此,您可以知道值是否正确,但是您不能获得无效的值。
您可以通过将各个按键推入缓冲区来解决此问题。但是,由于复制/粘贴,输入字段吞没某些键,在光标周围移动和插入键等,保持缓冲区与实际值之间的同步具有挑战性。为所有这些实现可靠的跨平台支持似乎是过分的。更好的方法是采用其他方式输入数字,例如滑块。 This resource covers the basics of designing number inputs
因此,您只需要知道当前输入是否有效以及是否按下了最后一个键即可。问题是某些无效输入,例如“4。”可能导致有效的输入“ 4.1”。因此,在输入变为无效的情况下仅吞下最后一个键是不可能的。
您可以实施以下规则:如果在2次击键(或1秒)内未将无效输入转换为有效输入,则输入将返回吞噬无效输入的最后一个有效状态。但是,我认为这会造成UX问题,因为用户可能不习惯这种行为,并且为用户提交技术上有效但不需要的值打开了大门。
核心问题:
有没有一种方法可以检查和验证输入?
是否有一种方法可以将输入标记为数字,而不必使用类型= number的后勤包?
显然不是。
是的,这是通过重新考虑如何输入数字值的方式。
答案 7 :(得分:-1)
这可能是您要寻找的:
此输入会吃掉所有数字和“。”以外的角色。
let prev = "";
function keyUp(event) {
if ((!event.target.value && event.keyCode !== 8) || event.target.value.indexOf('e') !== -1 || parseFloat(event.target.value) == NaN) {
event.target.value = prev;
} else {
prev = event.target.value;
}
}
<input type="number" onkeyup="keyUp(event)">