Home > Enterprise >  Input for currency not treating 0 like other numbers after decimal
Input for currency not treating 0 like other numbers after decimal

Time:03-30

I'm make a react application that takes an input that should be shown to two decimal places. When the default input has a one number after the decimal, it should add a second number with a 0 after it. It also lets me add infinite amounts of "0"s, but caps any other number at 2 decimal places.

Two different problems pictured:

Case 1. This is how the input looks when first loaded. The preferred display would be 1.60 (two decimal places)

enter image description here

Case 2. Current behavior allows the user to add infinite 0s (any other number it caps at 2 decimal places). Expected behavior should cap all numbers including 0s at 2 decimal places.

enter image description here

function ProductMaterial() {
        const [name, setName] = useState("");

        function handleChange(e) {
            let val = e.target.value;
            if (val.includes(".") && val.split(".")[1].length > 2) {
            } 
            else {
                setName(parseFloat(val));
                setMaterialState(parseFloat(val));
            }

        }

        return (
            <div className="input-group-sm col-xs-2 material input-group">
                <div className="input-group-prepend">
                    <span className="input-group-text">$</span>
                </div>
                <input
                    className="form-control"
                    type="number"
                    min="0.00"
                    onChange={handleChange}
                    value={product.material}
                />
            </div>
        );
    }

Here is the code for setMaterialState. It changes the product.material value, and then calls setMaterial() in a useEffect() function. The setMaterial() takes the id of the product, and the new material value and saves it to state.

    function setMaterialState(newMaterial) {
        product.material = newMaterial;
    }
    
    useEffect(() => {
        setMaterial(product.id, product.material);
    }, [product.material]);

I know that the issue here is that on first load nothing is triggering the onChange() function. I've tried setting value={product.material} to value={product.material.toFixed(2)} but it makes it difficult to fix the input. Is there a good way to initialize it before, maybe using a UseEffect() statement? And on top of this I'm not sure why the 0s can be added indefinitely.


Update: The first problem with the leading 0s was solved by using the onKeyPress= answer suggested by Photonic.

However, I'm still struggling on the forcing it to be two decimal places when there is a 0 at the end problem. I'm realizing that the issue with not starting doing 1.60 is due to it being converted to a float value and not being a string. I tried doing a UseEffect() [] and force it to go to 2 decimal places with product.material.toFixed(); as well as modify the data to start with being 1.60, but it seems like the only way to force the two decimal places is keeping it as a string or converting it to a string by using product.material.toFixed(2). The value in the input value={product.material} need to be a number to correctly execute calculations and collect user input. I'm not sure what the best solution for this is.

CodePudding user response:

I dont know how you are initializing the first load but you can use UseEffect() to fix the decimal place issue like you mentioned.

For the infinite decimal places...

onChange is an event that is already happen, you might want to try changing from onChange to onKeyDown or onKeyPress and in your code you can add e.preventDefault() to stop number from being entered

if (val.includes(".") && val.split(".")[1].length > 2) {
   e.preventDefault()
}

CodePudding user response:

If you want to call a function when the 'component did mount' you can use

useEffect(yourFunction(){}, [])
  • Related