限制输入 HTML 中的最大和最小时间 [已关闭]

Limit max and min time in input HTML [closed]

提问人:Paul 提问时间:11/13/2023 最后编辑:taoPaul 更新时间:11/14/2023 访问量:144

问:


编辑问题以包括所需的行为、特定问题或错误以及重现问题所需的最短代码。这将有助于其他人回答这个问题。

11天前关闭。

我有一个简单的代码,允许用户输入分钟和秒(网站是用 react 编写的)。

<div>
  <span>
    <input defaultValue="0" maxlength="2"/>
  </span>
<span>m</span>
<span>
    <input defaultValue="10" maxLength='2' />
  </span>
  <span>s</span>
</div>

但我想改进我的功能,这就是我求助于你的原因。

目前,用户可以输入任何数字 <= 99(在秒列中,他可以输入 99)和任何字符,但我希望用户能够输入至少 5 秒和最多 20 分钟的时间。

告诉我如何将输入的字符限制为仅数字,并限制最大和最短输入时间。

JavaScript HTML ReactJS 输入

评论

0赞 Paul 11/13/2023
@ProfessorAbronsius 是的,您的选择有效,谢谢!但是用户仍然可以输入 20 分 30 秒的时间段,我想将最大时间限制为 20 分 0 秒
0赞 jsejcksn 11/13/2023
编辑问题以包含一个最小的可重现示例,包括状态变量、负责呈现现有 JSX 的完整函数等。有关详细信息,请参阅如何询问
1赞 tao 11/14/2023
@nazarmammedov,请不要从有关表单元素的问题中删除标签。React 在处理表单方面有其特殊性,即使 JSX 看起来像普通的 HTML,标签也意味着用户正在寻找一个对 react 友好的解决方案。一般而言,您应避免删除专业领域之外的技术标签。reactjsreactjs

答:

-1赞 Puffer 11/13/2023 #1

您可以使用输入的 onChange 处理程序对其进行验证。

   <input value={month} maxlength="2" onChange={(e) => {
         validationFunc(e.target.value)
         setMonth(e.target.value);
    }}/>

您可以在 validtionFunc 中验证输入数据。
谢谢。

1赞 tao 11/13/2023 #2

您必须将 与适当的 和 一起使用。<input type="number" />minmax

为了实现自定义限制,下面是一个概念证明,将时间值(以秒为单位)保持在状态内,然后将其转换为每个输入的分钟和秒数:

const { useState, useCallback } = React
const limitValue = (min, max, val) => Math.min(max, Math.max(min, val))
const App = () => {
  const [value, setValue] = useState(10)
  const onInput = useCallback(
    (val, minutes) =>
      setValue((prev) =>
        limitValue(
          5,
          1200,
          minutes ? val * 60 + (prev % 60) : ~~(prev / 60) * 60 + val
        )
      ),
    []
  )
  return (
    <div>
      <span>
        <input
          type="number"
          min={0}
          max={20}
          value={~~(value / 60)}
          onInput={({ target: { value } }) => onInput(+value, true)}
        />
        m
      </span>
      <span>
        <input
          type="number"
          min={-1}
          max={60}
          value={value % 60}
          onInput={({ target: { value } }) => onInput(+value)}
        />
        s
      </span>
      <pre>
        {JSON.stringify(
          {
            value,
            minutes: ~~(value / 60),
            seconds: value % 60
          },
          null,
          2
        )}
      </pre>
    </div>
  )
}
ReactDOM.createRoot(root).render(<App />)
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<div id="root"></div>

评论

1赞 tao 11/13/2023
致反对者:我将不胜感激任何关于如何改进问题的反馈,谢谢。
0赞 Paul 11/13/2023
感谢您关注我的问题。我没有投反对票。我想问你关于改进的问题:目前用户可以手动输入任何数字,这可以通过某种方式解决吗?
0赞 tao 11/13/2023
我明白你的意思,是的,你需要使用 and .更新了答案。Math.min()Math.max()
0赞 Paul 11/13/2023
是的,谢谢!但是我们仍然可以输入一个时间段,例如,20 分 30 秒,最大值应该是 20 分钟
0赞 tao 11/13/2023
我之前已经修复了几次编辑。现在应该没事了。
-1赞 Professor Abronsius 11/13/2023 #3

没有经过全面测试,但您可以尝试这样的方法。

使用适当的属性设置输入字段后,例如并确保将 and 属性设置为您的条件(最多 20 分钟,最短 5 秒),然后您可以使用绑定到合适父级(在本例中的文档,但可以/应该更集中)的委托侦听器来监视事件。typetype='number'minmaxinput

事件处理程序标识所有相关的元素(此处按名称),并对每个元素的值执行一些基本操作,以创建以秒为单位的总时间值。如果该时间值超出您的限制,请警告用户和/或设置您自己的默认值。input

document.addEventListener('input',e=>{
  if( ['minutes','seconds'].includes( e.target.name ) ){
    
    const mapcallback=(n)=>n.name=='minutes' ? n.value * 60 : n.value;
    const reducecallback=(a,b)=>a+parseInt(b);
    /*
      find the numeric input elements,
      convert minutes to seconds and
      create sum of both mins & secs values.
    */
    let total=[...document.querySelectorAll('input[type="number"]')]
        .map( mapcallback )
        .reduce( reducecallback, 0 );
    
    /* warn the user if selected values are out of range.*/
    if( total < 5 ){
      console.log('Must be at least 5s');
    }
    if( total > 1200 ){
      console.log('Can be no more than 1200s / 20mins');
      document.querySelector('[name="seconds"]').value=0;
    }
  }
});
<div>
  <label>
    <input name='minutes' type='number' min=0 max=20 value=0 maxlength=2 />
    <span>m</span>
  </label>
  
  <label>
    <input name='seconds' type='number' min=5 max=59 value=5 maxlength=2 />
    <span>s</span>
  </label>
</div>

评论

0赞 Professor Abronsius 11/13/2023
根据 @tao 的评论 - 如果反对者能评论他们决定投反对票的原因,那就太好了,因为这可能有助于获得更好的结果。
0赞 tao 11/13/2023
我在这里投了反对票:在文档中的每个输入上绑定一个回调,然后根据匹配其名称来过滤运行代码是一种糟糕的模式,尤其是在 Stack Overflow 答案中使用时,也应该针对有类似问题的用户。恕我直言,它有巨大的潜力造成不必要的实施问题。
0赞 Professor Abronsius 11/13/2023
只有一个听众,所以不确定是什么意思。binding a callback on every single input in the document
0赞 tao 11/13/2023
不过,我确实喜欢使用单个值(以秒为单位)并计算它是否在 5 到 1200 之间的想法。这就是应该做的。但我仍然会使用useState()
1赞 Professor Abronsius 11/13/2023
我确实提到过,委托的听众应该更加专注 - 即:绑定到合适的父级,但鉴于问题中引用的 HTML 数量很少,不清楚合适的父级是什么。我现在看到 Op 确实提到了如此道歉。react
-1赞 Emtiaz Zahid 11/13/2023 #4

要仅使用 Javascript 执行此操作,并在无效输入时显示警报:

  <form>
    <label for="minutes">Minutes:</label>
    <input type="number" id="minutes" min="0" max="20" oninput="validateTime()" required>
    
    <label for="seconds">Seconds:</label>
    <input type="number" id="seconds" min="0" max="59" oninput="validateTime()" required>
  </form>

  <script>
    function validateTime() {
      var minutes = parseInt(document.getElementById('minutes').value, 10);
      var seconds = parseInt(document.getElementById('seconds').value, 10);

      if (isNaN(minutes) || isNaN(seconds)) {
        alert('Please enter valid numbers for minutes and seconds.');
        return;
      }

      if (minutes < 0 || minutes > 20 || seconds < 0 || seconds > 59) {
        alert('Please enter a valid time. Minutes should be between 0 and 20, and seconds between 0 and 59.');
        return;
      }

      // You can do something with the valid input here, or remove this alert.
      alert('Valid input: ' + minutes + ' minutes ' + seconds + ' seconds');
    }
  </script>