1

I tried doing this by creating a text that overlays the textbox but I did not continue because it will further complicate things.

I rollback the code.

######################################################################################### Here is my rollbacked code:

const StepFour = (props) => {

const [number, setNumber] = useState('')
const [expiry, setExpiry] = useState('')
const [cvc, setCvc] = useState('')
const [focus, setFocus] = useState('')

const [month, setMonth] = useState('')
const [year, setYear] = useState('')

const [cardNumError, setCardNumError] = useState(false)

const dispatch = useDispatch()

const cardList = ['4571736000000075']

const handleCardNumError = () => {
    if (!cardList.includes(number) ) {
        setCardNumError(true)
    } else {
        setCardNumError(false)
    }
}

const handleCardNumError2 = () => {
    if (!cardList.includes(number) && number.length === 19 ) {
        setCardNumError(true)
    } else {
        setCardNumError(false)
    }
}

useEffect(() => {
    setExpiry(month + '/' + year)
}, [month, year])



const classes = useStyles()
return (
        <div className={classes.mainContainer}>
            <div>
                <Cards
                    number={number}
                    expiry={expiry}
                    cvc={cvc}
                    focused={focus}/>
            </div>
            <div className={classes.formInputContatiner}>
                <div>
                    <Typography
                        variant="subtitle1"
                        style={{
                            color: "black", 
                            textAlign: "left",
                            marginBottom: "5px"
                        }}>
                        Card Number
                    </Typography>
                    <div className={classes.cardNumber}>
                        <div className={classes.grid}>
                            <div className={classes.cardNumContainer}>
                                <input 
                                    className={classes.inputStyle} 
                                    type='tel'
                                    name='number'
                                    maxLength='16'
                                    placeholder='1234 1234 1234 1234'
                                    value={number}
                                    style={{
                                        color: "black",
                                        border: "1px solid",
                                        borderColor: cardNumError ? 'red' : '#ccc',
                                        display: "inline-block"
                                    }}
                                    onChange={e => {
                                        let val = e.target.value
                                        const re = /^[0-9\b]+$/
                                        if (val === '' || re.test(val)) {
                                            setNumber(val)
                                            dispatch(getCN(val))
                                        }
                                        handleCardNumError2()
                                        
                                    }}
                                    onFocus={e => {
                                        setFocus(e.target.name)
                                    }}
                                    onBlur={() => {
                                        handleCardNumError()
                                    }}/>
                            </div>
                        </div>
                        {cardNumError === true ? <Typography
                            variant="subtitle1"
                            style={{
                                color: "red", 
                            }}>
                            Your card number is invalid.
                        </Typography> : null}
                    </div>
                    
                </div>
                <div>
                    <Typography
                        variant="subtitle1"
                        style={{
                            color: "black", 
                            textAlign: "left",
                            marginBottom: "5px"
                        }}>
                        Month and Year
                    </Typography>
                    <div className={classes.dateAndCVC}>
                        <input 
                            className={classes.inputStyle2} 
                            type="text"
                            name='month'
                            placeholder='MM'
                            value={month}
                            onChange={e => {
                                setMonth(e.target.value)
                                dispatch(getCDM(e.target.value))
                            }}
                            onFocus={e => setFocus(e.target.name)}/>
                        <input 
                            className={classes.inputStyle2} 
                            type="text"
                            name='year'
                            placeholder='YY'
                            value={year}
                            onChange={e => {
                                setYear(e.target.value)
                                dispatch(getCDY(e.target.value))
                            }}
                            onFocus={e => setFocus(e.target.name)}/>
                    </div>   
                </div>   
                <div>
                    <Typography
                        variant="subtitle1"
                        style={{
                                color: "black", 
                                textAlign: "left",
                                marginBottom: "5px"
                            }}>
                        CVC
                    </Typography>
                    <input 
                            className={classes.inputStyle2} 
                            type="tel"
                            name='cvc'
                            placeholder='CVC'
                            value={cvc}
                            onChange={e => {
                                setCvc(e.target.value)
                                dispatch(getCCVC(e.target.value))
                            }}
                            onFocus={e => setFocus(e.target.name)}/>
                </div>
            </div>
        </div>
)

}

export default StepFour

Here is the output:

enter image description here

  • Does this answer your question? [Javascript credit card field - Add space every four chars - Backspace not working properly](https://stackoverflow.com/questions/36568425/javascript-credit-card-field-add-space-every-four-chars-backspace-not-workin) – vanowm Jul 01 '21 at 22:37
  • I tried it but it does not work in my code. – Franz Dayrit Jul 02 '21 at 04:53

1 Answers1

2

This is my solution. I handle when the card will display by check if the input has already 4 characters length and then add space in it.

The important part is when you type each character you have to remove all old space before add space again otherwise it will fill the input with a lot of weird space.

Here is my code. You can see its action here

import React, { useState } from 'react';

function App() {
    const [card, setCard] = useState('')

    const handleCardDisplay = () => {
        const rawText = [...card.split(' ').join('')] // Remove old space
        const creditCard = [] // Create card as array
        rawText.forEach((t, i) => {
            if (i % 4 === 0 && i !== 0) creditCard.push(' ') // Add space
            creditCard.push(t)
        })
        return creditCard.join('') // Transform card array to string
    }

    return (
        <div>
            <input 
                value={handleCardDisplay()} 
                onChange={(e) => setCard(e.target.value)}
            />
        </div>
    )
}

export default App;