如何使此代码适用于包含 (mm/yy) 模型的到期日期 TextInput?
How can I make this code work for expiry date TextInput which includes (mm/yy) model?
我想创建一个包含到期日 TextInput
的结帐表单。它看起来像这样 (MM/YY)。添加前 2 位数字后,它会自动添加/然后该人可以输入年份的最后 2 位数字。我在另一个问题上找到了这段代码。但它不起作用。当您在表单中键入时,不会键入任何内容。这是代码。我怎样才能让这段代码按需要工作?
constructor() {
super()
this.state = {
isReady: false
}
}
componentDidMount() {
this.setState({
isReady: true
})
}
onChange(text) {
let newText = '';
let numbers = '0123456789';
for (var i = 0; i < text.length; i++) {
if ( numbers.indexOf(text[i]) > -1 ) {
newText = newText + text[i];
}
}
this.setState({myNumber: newText})
}
formatFunction(cardExpiry = ""){
//expiryDate will be in the format MMYY, so don't make it smart just format according to these requirements, if the input has less than 2 character return it otherwise append `/` character between 2nd and 3rd letter of the input.
if(cardExpiry.length < 2){
return cardExpiry;
}
else{
return cardExpiry.substr(0, 2) + "/" + (cardExpiry.substr(2) || "")
}
}
inputToValue(inputText){
//if the input has more than 5 characters don't set the state
if(inputText.length < 6){
const tokens = inputText.split("/");
// don't set the state if there is more than one "/" character in the given input
if(tokens.length < 3){
const month = Number(tokens[1]);
const year = Number(tokens[2]);
//don't set the state if the first two letter is not a valid month
if(month >= 1 && month <= 12){
let cardExpiry = month + "";
//I used lodash for padding the month and year with zero
if(month > 1 || tokens.length === 2){
// user entered 2 for the month so pad it automatically or entered "1/" convert it to 01 automatically
cardExpiry = _.padStart(month, 2, "0");
}
//disregard changes for invalid years
if(year > 1 && year <= 99){
cardExpiry += year;
}
this.setState({cardExpiry});
}
}
}
}
render (){
let {cardExpiry} = this.state;
return (
<Image style={styles.image} source={require('../img/cover.jpg')}
>
<Content style={styles.content}>
<Form>
<Item >
<Icon active name='card'/>
<Input keyboardType='numeric' maxLength={16} placeholder='Card Number'
onChangeText = {(text)=> this.onChange(text)}
value = {this.state.myNumber}/>
</Item>
<Grid>
<Row>
<Col>
<Item style={{ marginBottom:10}}>
<Icon active name='calendar' />
<Input keyboardType='numeric' placeholder='MM/YY'
value = {this.formatFunction(cardExpiry)}
onChangeText={this.inputToValue.bind(this)}/>
</Item>
</Col>
<Col>
<Item style={{ marginBottom:10}}>
<Icon active name='lock' />
<Input maxLength={3} secureTextEntry={true} placeholder='CVV'/>
</Item>
</Col>
</Row>
</Grid>
使用此代码来处理您的问题:
constructor(props) {
super(props);
this.state = { text: '' };
}
handleChange = (text) => {
let textTemp = text;
if (textTemp[0] !== '1' && textTemp[0] !== '0') {
textTemp = '';
}
if (textTemp.length === 2) {
if (parseInt(textTemp.substring(0, 2)) > 12 || parseInt(textTemp.substring(0, 2)) == 0) {
textTemp = textTemp[0];
} else if (this.state.text.length === 2) {
textTemp += '/';
} else {
textTemp = textTemp[0];
}
}
this.setState({text: textTemp})
}
render() {
return (
<TextInput
keyboardType={'numeric'}
onChangeText={this.handleChange}
value={this.state.text}
maxLength={5}
/>
);
}
添加解决上述解决方案中无法删除“/”的答案。
const setExpiry = (e) => {
const { name, value } = e.target;
var v = value;
if (v.includes('/') == false) {
if (v.length === 4) {
var a = v.substr(0, 2);
var ae = v.charAt(v.length - 2) + v.charAt(v.length - 1);
e.target.value = a + '/' + ae;
}
}
}
在使用 Month/Year 搜索了很多 Picker 之后,我暂时为到期日期创建了一个逻辑。
希望这会对某人有所帮助。
const onCardExpiryDateChange = (prevValue:string, currentValue: string) => {
if (currentValue?.includes(',') || currentValue?.includes('-') || currentValue?.includes('.')) {
return prevValue
} else {
let textTemp = currentValue
if (textTemp[0] !== '0' && textTemp[0] !== '1' && textTemp[0] !== '2' && textTemp[0] !== '3') {
textTemp = '';
} else if ((prevValue?.length === 5) && currentValue.length === prevValue.length-1) {
textTemp = textTemp?.slice(0, -3)
} else if (textTemp.length === 6 && (textTemp[5] == '0' || textTemp[5] == '1')){
textTemp = textTemp?.slice(0, -1)
}
else if (textTemp.length === 7 && textTemp[6] == '0') {
textTemp = textTemp?.slice(0, -1)
} else if (textTemp.length === 2) {
if (parseInt(textTemp?.substring(0, 2)) > 12 || parseInt(textTemp?.substring(0, 2)) == 0) {
textTemp = textTemp?.slice(0, -1)
} else if (textTemp?.length === 2) {
textTemp += ' / ';
} else {
textTemp = textTemp[0];
}
}
return textTemp
}
}
正如@AndroConsis 在@Vahid Boreiri 的回答中指出的那样,在长度 2 之后添加“/”的唯一问题是在删除到期日期时它会不断添加“/”。要解决此问题,可以添加条件退格标志。
const [backspaceFlag, setBackspaceFlag] = React.useState(false);
const [expiratoinDate, setExpirationDate] = React.useState('');
const handleExpirationDate = (text) => {
let textTemp = text;
if (textTemp[0] !== '1' && textTemp[0] !== '0') {
textTemp = '';
}
if (textTemp.length === 2) {
if (parseInt(textTemp.substring(0, 2)) > 12 || parseInt(textTemp.substring(0, 2)) == 0) {
textTemp = textTemp[0];
} else if (text.length === 2 && !backspaceFlag) {
textTemp += '/';
setBackspaceFlag(true);
} else if (text.length === 2 && backspaceFlag) {
textTemp = textTemp[0];
setBackspaceFlag(false);
} else {
textTemp = textTemp[0];
}
}
setExpirationDate(textTemp);
};
const [expiratoinDate, setExpirationDate] = useState(''); const [backspaceFlag, setBackspaceFlag] = useState(false);
const handleExpirationDate = (text) => {
if(backspaceFlag===false){
if(text.length==2){ setExpirationDate(text+"/"); setBackspaceFlag(true) }
`else{
setExpirationDate(text)
}`
}
else{
if(text.length==2){
let text2=expiratoinDate.slice(0,1)
`setExpirationDate(text2);`
`setBackspaceFlag(false)
}`
`else{
setExpirationDate(text)
}`
}
`};`
我想创建一个包含到期日 TextInput
的结帐表单。它看起来像这样 (MM/YY)。添加前 2 位数字后,它会自动添加/然后该人可以输入年份的最后 2 位数字。我在另一个问题上找到了这段代码。但它不起作用。当您在表单中键入时,不会键入任何内容。这是代码。我怎样才能让这段代码按需要工作?
constructor() {
super()
this.state = {
isReady: false
}
}
componentDidMount() {
this.setState({
isReady: true
})
}
onChange(text) {
let newText = '';
let numbers = '0123456789';
for (var i = 0; i < text.length; i++) {
if ( numbers.indexOf(text[i]) > -1 ) {
newText = newText + text[i];
}
}
this.setState({myNumber: newText})
}
formatFunction(cardExpiry = ""){
//expiryDate will be in the format MMYY, so don't make it smart just format according to these requirements, if the input has less than 2 character return it otherwise append `/` character between 2nd and 3rd letter of the input.
if(cardExpiry.length < 2){
return cardExpiry;
}
else{
return cardExpiry.substr(0, 2) + "/" + (cardExpiry.substr(2) || "")
}
}
inputToValue(inputText){
//if the input has more than 5 characters don't set the state
if(inputText.length < 6){
const tokens = inputText.split("/");
// don't set the state if there is more than one "/" character in the given input
if(tokens.length < 3){
const month = Number(tokens[1]);
const year = Number(tokens[2]);
//don't set the state if the first two letter is not a valid month
if(month >= 1 && month <= 12){
let cardExpiry = month + "";
//I used lodash for padding the month and year with zero
if(month > 1 || tokens.length === 2){
// user entered 2 for the month so pad it automatically or entered "1/" convert it to 01 automatically
cardExpiry = _.padStart(month, 2, "0");
}
//disregard changes for invalid years
if(year > 1 && year <= 99){
cardExpiry += year;
}
this.setState({cardExpiry});
}
}
}
}
render (){
let {cardExpiry} = this.state;
return (
<Image style={styles.image} source={require('../img/cover.jpg')}
>
<Content style={styles.content}>
<Form>
<Item >
<Icon active name='card'/>
<Input keyboardType='numeric' maxLength={16} placeholder='Card Number'
onChangeText = {(text)=> this.onChange(text)}
value = {this.state.myNumber}/>
</Item>
<Grid>
<Row>
<Col>
<Item style={{ marginBottom:10}}>
<Icon active name='calendar' />
<Input keyboardType='numeric' placeholder='MM/YY'
value = {this.formatFunction(cardExpiry)}
onChangeText={this.inputToValue.bind(this)}/>
</Item>
</Col>
<Col>
<Item style={{ marginBottom:10}}>
<Icon active name='lock' />
<Input maxLength={3} secureTextEntry={true} placeholder='CVV'/>
</Item>
</Col>
</Row>
</Grid>
使用此代码来处理您的问题:
constructor(props) {
super(props);
this.state = { text: '' };
}
handleChange = (text) => {
let textTemp = text;
if (textTemp[0] !== '1' && textTemp[0] !== '0') {
textTemp = '';
}
if (textTemp.length === 2) {
if (parseInt(textTemp.substring(0, 2)) > 12 || parseInt(textTemp.substring(0, 2)) == 0) {
textTemp = textTemp[0];
} else if (this.state.text.length === 2) {
textTemp += '/';
} else {
textTemp = textTemp[0];
}
}
this.setState({text: textTemp})
}
render() {
return (
<TextInput
keyboardType={'numeric'}
onChangeText={this.handleChange}
value={this.state.text}
maxLength={5}
/>
);
}
添加解决上述解决方案中无法删除“/”的答案。
const setExpiry = (e) => {
const { name, value } = e.target;
var v = value;
if (v.includes('/') == false) {
if (v.length === 4) {
var a = v.substr(0, 2);
var ae = v.charAt(v.length - 2) + v.charAt(v.length - 1);
e.target.value = a + '/' + ae;
}
}
}
在使用 Month/Year 搜索了很多 Picker 之后,我暂时为到期日期创建了一个逻辑。 希望这会对某人有所帮助。
const onCardExpiryDateChange = (prevValue:string, currentValue: string) => {
if (currentValue?.includes(',') || currentValue?.includes('-') || currentValue?.includes('.')) {
return prevValue
} else {
let textTemp = currentValue
if (textTemp[0] !== '0' && textTemp[0] !== '1' && textTemp[0] !== '2' && textTemp[0] !== '3') {
textTemp = '';
} else if ((prevValue?.length === 5) && currentValue.length === prevValue.length-1) {
textTemp = textTemp?.slice(0, -3)
} else if (textTemp.length === 6 && (textTemp[5] == '0' || textTemp[5] == '1')){
textTemp = textTemp?.slice(0, -1)
}
else if (textTemp.length === 7 && textTemp[6] == '0') {
textTemp = textTemp?.slice(0, -1)
} else if (textTemp.length === 2) {
if (parseInt(textTemp?.substring(0, 2)) > 12 || parseInt(textTemp?.substring(0, 2)) == 0) {
textTemp = textTemp?.slice(0, -1)
} else if (textTemp?.length === 2) {
textTemp += ' / ';
} else {
textTemp = textTemp[0];
}
}
return textTemp
}
}
正如@AndroConsis 在@Vahid Boreiri 的回答中指出的那样,在长度 2 之后添加“/”的唯一问题是在删除到期日期时它会不断添加“/”。要解决此问题,可以添加条件退格标志。
const [backspaceFlag, setBackspaceFlag] = React.useState(false);
const [expiratoinDate, setExpirationDate] = React.useState('');
const handleExpirationDate = (text) => {
let textTemp = text;
if (textTemp[0] !== '1' && textTemp[0] !== '0') {
textTemp = '';
}
if (textTemp.length === 2) {
if (parseInt(textTemp.substring(0, 2)) > 12 || parseInt(textTemp.substring(0, 2)) == 0) {
textTemp = textTemp[0];
} else if (text.length === 2 && !backspaceFlag) {
textTemp += '/';
setBackspaceFlag(true);
} else if (text.length === 2 && backspaceFlag) {
textTemp = textTemp[0];
setBackspaceFlag(false);
} else {
textTemp = textTemp[0];
}
}
setExpirationDate(textTemp);
};
const [expiratoinDate, setExpirationDate] = useState(''); const [backspaceFlag, setBackspaceFlag] = useState(false);
const handleExpirationDate = (text) => {
if(backspaceFlag===false){
if(text.length==2){ setExpirationDate(text+"/"); setBackspaceFlag(true) }
`else{
setExpirationDate(text)
}`
}
else{
if(text.length==2){
let text2=expiratoinDate.slice(0,1)
`setExpirationDate(text2);`
`setBackspaceFlag(false)
}`
`else{
setExpirationDate(text)
}`
}
`};`