React-如何将电话号码格式化为用户类型

时间:2019-05-05 01:07:56

标签: javascript regex reactjs validation formatting

我需要将10位数字的字符串格式设置为以下格式:“(123)456-7890”。 但是,我需要在用户输入时发生这种情况。因此,如果用户仅输入了3位数字,则输入应显示:“(123)”。 如果他们输入了5位数字,则输入内容应显示为:'(123)45'

使用我当前的代码,仅在输入第10个字符后才进行格式化。我希望它能从第三个字符开始对其进行格式化。

const phoneRegex = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/

const handleInput = (value) => {
  return (
    value.replace(phoneRegex, '($1) $2-$3')
  )
}

class FindASubscriber extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      value: ''
    }
  }

  render() {
    const { label, placeholder, feedback } = this.props
    const { value} = this.state
    return (
      <div className="find__a__subscriber">
        <FlexGrid>
          <FlexGrid.Col>
            <FlexGrid.Row>
              <Input
                feedback={feedback}
                label={label}
                type="text"
                pattern="[0-9]*"
                placeholder={placeholder}
                value={handleInput(value)}
                maxLength="10"
                onChange={
                 (event) => this.setState({value: event.target.value})
                }
              />
            </FlexGrid.Row>
          </FlexGrid.Col>
        </FlexGrid>
      </div>
    )
  }
}```

5 个答案:

答案 0 :(得分:1)

仅当输入十位数字(3、3,然后是4)时,当前代码的正则表达式才匹配。您可以更新正则表达式以接受一定范围的数字,例如:

^\(?([0-9]{0,3})\)?[-. ]?([0-9]{0,3})[-. ]?([0-9]{0,4})$

或者您可以让正则表达式简单地确保输入0-10个数字([0-9] {0,10}),然后将字符串自己分成长度分别为3、3和4的子字符串。后一种方法似乎更好,因为您只想根据用户输入的位数显示某些字符:

  

1->(1

     

123->(123)

     

1234567->(123)456-7

     

1234567890->(123)456-7890

您将不得不处理所有这些情况,而简单的替换将无法解决这些情况。

答案 1 :(得分:0)

我已经使用了这个库:https://www.npmjs.com/package/libphonenumber-js它具有一个AsYouType函数,您可以在输入中使用

答案 2 :(得分:0)

所有与格式化有关。任何可打印字符的键
应该导致输入字段的重写。
这样,无论用户做什么,用户都只能看到有效的格式化字段。

正则表达式很简单^\D*(\d{0,3})\D*(\d{0,3})\D*(\d{0,4})

function getFormattedPhoneNum( input ) {
  let output = "(";
  input.replace( /^\D*(\d{0,3})\D*(\d{0,3})\D*(\d{0,4})/, function( match, g1, g2, g3 )
      {
        if ( g1.length ) {
          output += g1;
          if ( g1.length == 3 ) {
              output += ")";
              if ( g2.length ) {
                  output += " " + g2; 
                  if ( g2.length == 3 ) {
                      output += " - ";
                      if ( g3.length ) {
                          output += g3;
                      }
                  }
              }
           }
        }
      }       
    );        
  return output;
 }       

console.log( getFormattedPhoneNum("") );
console.log( getFormattedPhoneNum("2") );
console.log( getFormattedPhoneNum("asdf20as3d") );
console.log( getFormattedPhoneNum("203") );
console.log( getFormattedPhoneNum("203-44") );
console.log( getFormattedPhoneNum("444sg52asdf22fd44gs") );
console.log( getFormattedPhoneNum("444sg526sdf22fd44gs") );
console.log( getFormattedPhoneNum("444sg526sdf2244gs") );
console.log( getFormattedPhoneNum(" ra098 848 73653k-atui ") );

您甚至可以变得更奇特,并在人物的下划线处显示
应该在任何给定时间。
喜欢
(___) ___ - ____
(20_) ___ - ____
(123) 456 - ____

等...(让我知道是否要这样)

答案 3 :(得分:0)

您可以像这样normalize input

  • value是关于event.target.value的最新信息
  • previousValue已被验证并设置为state

这种结构的结构可以防止无效字符更新输入,并将输入限制为10个数字。

单击下面的Run code snippet按钮以获取可用的示例。


const normalizeInput = (value, previousValue) => {
  // return nothing if no value
  if (!value) return value; 

  // only allows 0-9 inputs
  const currentValue = value.replace(/[^\d]/g, ''); 

  if (!previousValue || value.length > previousValue.length) {

    // returns: "x", "xx", "xxx"
    if (currentValue.length <= 3) return currentValue; 

    // returns: "(xxx)"
    if (currentValue.length === 3) return `(${currentValue})`; 

    // returns: "(xxx) x", "(xxx) xx", "(xxx) xxx",
    if (currentValue.length <= 6) return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3)}`; 

    // returns: "(xxx) xxx-"
    if (currentValue.length === 6) return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3)}-` 

    // returns: "(xxx) xxx-x", "(xxx) xxx-xx", "(xxx) xxx-xxx", "(xxx) xxx-xxxx"
    return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3, 6)}-${currentValue.slice(6, 10)}`; 
  }
};

const normalizeInput = (value, previousValue) => {
  if (!value) return value;
  const currentValue = value.replace(/[^\d]/g, '');
  if (!previousValue || value.length > previousValue.length) {
    if (currentValue.length <= 3) return currentValue;
    if (currentValue.length === 3) return `(${currentValue})`;
    if (currentValue.length <= 6) return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3)}`;
    if (currentValue.length === 6) return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3)}-`
    return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3, 6)}-${currentValue.slice(6, 10)}`;
  }
};

const validateInput = value => {
  let error = ""
  
  if (!value) error = "Required!"
  else if (value.length !== 14) error = "Invalid phone format. ex: (555) 555-5555";
  
  return error;
};
    
class Form extends React.Component {
  constructor() {
    super();
    
    this.state = { phone: "", error: "" };
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleReset = this.handleReset.bind(this);
  }
  
  handleChange({ target: { value } }) {
    const normalized = normalizeInput(value, this.state.phone);
    
    this.setState({ phone: normalized });
  };
  
  handleSubmit(e) {
    e.preventDefault();
    const error = validateInput(this.state.phone);
    
    this.setState({ error }, () => {
       if(!error) {
         setTimeout(() => {
           alert(JSON.stringify(this.state, null, 4));
         }, 300)
       }
    });
  }
  
  handleReset() {
     this.setState({ phone: "", error: "" });
  };
  
  render() {
    return(
      <form className="form" onSubmit={this.handleSubmit}>
        <div className="input-container">
          <p className="label">Phone:</p>
          <input
            className="input"
            type="text"
            name="phone"
            placeholder="(xxx) xxx-xxxx"
            value={this.state.phone}
            onChange={this.handleChange}
          />
          {this.state.error && <p className="error">{this.state.error}</p>}
        </div>
        <div className="btn-container">
          <button 
             className="btn danger"
             type="button"
             onClick={this.handleReset}
           >
            Reset
          </button>
          <button className="btn primary" type="submit">Submit</button>
        </div>
      </form>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('root')
);
html {
  font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
  font-size: 16px;
  font-weight: 400;
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
  background: #fff;
  color: #666;
}

.btn {
  color: #fff;
  border: 1px solid transparent;
  margin: 0 10px;
  cursor: pointer;
  text-align: center;
  box-sizing: border-box;
  padding: 0 30px;
  vertical-align: middle;
  font-size: .875rem;
  line-height: 38px;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
  transition: .1s ease-in-out;
  transition-property: color,background-color,border-color;
}

.btn:focus {
  outline: 0;
}

.btn-container {
  text-align: center;
  margin-top: 10px;
}

.form {
  width: 550px;
  margin: 0 auto;
}

.danger {
  background-color: #f0506e;
  color: #fff;
  border: 1px solid transparent;
}
 
.danger:hover {
  background-color: #ee395b;
  color: #fff;
}

.error {
  margin: 0;
  margin-top: -20px;
  padding-left: 26%;
  color: red;
  text-align: left;
}

.input {
  display: inline-block;
  height: 40px;
  font-size: 16px;
  width: 70%;
  padding: 0 10px;
  background: #fff;
  color: #666;
  border: 1px solid #e5e5e5;
  transition: .2s ease-in-out;
  transition-property: color,background-color,border;
 }

.input-container {
  width: 100%;
  height: 60px;
  margin-bottom: 20px;
  display: inline-block;
}

.label {
  width: 25%;
  padding-top: 8px;
  display: inline-block;
  text-align: center;
  text-transform: uppercase;
  font-weight: bold;
  height: 34px;
  border-top-left-radius: 4px;
  border-bottom-left-radius: 4px;
  background: rgb(238, 238, 238);
}

.primary {
  background-color: #1e87f0;
}

.primary:hover {
  background-color: #0f7ae5;
  color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>


<div id='root'>
</div>

答案 4 :(得分:0)

也许,以下内容对某人有用:

   onChange={(e) => {
                if (e.target.value.length < 13) {
                  var cleaned = ("" + e.target.value).replace(/\D/g, "");

                  let normValue = `${cleaned.substring(0, 3)}${
                    cleaned.length > 3 ? "-" : ""
                  }${cleaned.substring(3, 6)}${
                    cleaned.length > 6 ? "-" : ""
                  }${cleaned.substring(6, 11)}`;

                  handleChange(normValue);
                }
              }}