nosir / cleave.js

Format input text content when you are typing...
http://nosir.github.io/cleave.js
Apache License 2.0
17.96k stars 1.62k forks source link

Cleave.js React Bug when date pattern bound to state #551

Open igoriok1994 opened 4 years ago

igoriok1994 commented 4 years ago

Hello,

Found strange component behavior when using Cleave.js date input and datePattern is bound to state.

I have a dynamic calendar with Cleave.js input. Depending on my tree selections, calendar show days or months and I'm changing datePattern value in state expecting that Cleave input will see changes (by react vision, components should be dynamic, dependent on state changes).

Here is JsFiddle expamle: https://jsfiddle.net/kwdmg9cn/

Eg. with whole options object bound to state: https://jsfiddle.net/185ujqwo/

As you can see, placeholder is working dynamically, but datePattern not.

Valid to Cleave.js versions from 1.4.10 to 1.5.3

EGurney commented 2 years ago

I found that I had to create separate components for each option type.

So in your case, you would have 2 components, one for each set of config which depends on your state. You would conditionally render the component shown, which would just be a wrapper for the <Cleave /> component.

For example, I had to have 2 components for a zip/postal code input. Canada and USA have different formats for this value.

{data.countryCode === "CA" ? (
    <>
        <CleavePostalCodeInput value={data.zip} onChange={updateData} disabled={disabled} />
    </>
) : (
    <>
        <CleaveZipInput value={data.zip} onChange={updateData} disabled={disabled} />
    </>
)}

And one of the components is just showing Cleave with whatever options are needed.

import Cleave from "cleave.js/react";
import { DataInput } from "@/types/DataInput.type";

interface Props {
    value: string;
    disabled?: boolean;
    onChange: (e: DataInput) => void;
}

const CleavePostalCodeInput = ({ value, disabled, onChange }: Props): JSX.Element => {
    return (
        <Cleave
            className="border border-wordpresto-grey-200 px-3 py-2 rounded"
            name="billingAddress_zip"
            placeholder="xxx xxx"
            options={{
                uppercase: true,
                blocks: [3, 3],
                delimiter: " ",
                numericOnly: false,
            }}
            value={value}
            onChange={onChange}
            disabled={disabled}
        />
    );
};

export default CleavePostalCodeInput;

And for the Zip code

import Cleave from "cleave.js/react";
import { DataInput } from "@/types/DataInput.type";

interface Props {
    value: string;
    disabled?: boolean;
    onChange: (e: DataInput) => void;
}

const CleaveZipInput = ({ value, disabled, onChange }: Props): JSX.Element => {
    return (
        <Cleave
            className="border border-wordpresto-grey-200 px-3 py-2 rounded"
            name="billingAddress_zip"
            placeholder="xxxxx"
            options={{
                blocks: [5],
                numericOnly: true,
            }}
            value={value}
            onChange={onChange}
            disabled={disabled}
        />
    );
};

export default CleaveZipInput;

It's kinda lame... placeholder values update as expected based on state for me, but config seems to be tied to whatever options are originally set in the Cleave component and are not dynamic.