React - getting data-attribute from a a form input field based on object key

27 views Asked by At

My company has a web portal with a form on it for people needing help with accessibility to contact the company. Our company is now switching to React and I am trying to create the same form with the same functionality. There is an Email object that is submitted to the api created in the backend. The Email object has several fields, one of which is toEamilBody. All of the data from the accessibility form needs to be tied together into a string in a very specific way and saved as the value of toEmailBody. I am working on the method to create that string. As a preliminary matter, I am using react-hook-form, Yup, and Material UI.

I have five fields in my form: First Name, Last Name, Phone Number, Email Address, and Comments (all but phone are required). The string I am putting together is going to be a string of HTML elements interspersed with the form data. Here is how the string will look when the data is submitted to the backend (as you can see this is after I have filled out the Angular form on the old web portal:

"<table><tr><td>First Name</td><td>Bill</td></tr><tr><td>Last Name</td><td>Burr</td></tr><tr><td>Phone Number</td><td>4029601222</td></tr><tr><td>Email Address</td><td>[email protected]</td></tr><tr><td>Comments</td><td>hello</td></tr></table>"

The Angular method that puts this together starts the string with "". Then the method iterates over the form.controls Object keys. The form uses an InputWrapperComponent where it ends up retrieving the values of the labels for each input as well as the values for the inputs themselves. It then calls a method addRow that basically adds to the string: " + label + "" + value + "". at then end ot the iterations it slaps on the "".

Now the way it gets the value of the label seems kind of convoluted, and I don't really understand it, but I know it won't work in React because it's tied around the InputWrapperComponent and the Angular form.controls and such. But it's very important that I am able to use for the label value "First Name" as opposed to "firstName". So my plan was to insert an attribute data-label in my input element and set its value to "first Name" or what not and then retrieve it.

I can't seem to figure out the proper method to retrieve it though. I've looked up this question and seen answers referring to things such as e.target.getAttribute(data-pg) and such, but that doesn't work here because I am iterating through Object keys and as such have no e.target.

I'm not sure what else to say, so let me post my code. I'm going to leave some of the return off that's not relevant and just post the part of the return.

Here is my Accessibility.tsx file:

export default function Accessibility(props: any) {
    const [isIncompleteMsg, setIsIncompleteMsg] = useState(null);
    const validationSchema = Yup.object().shape(
        {
            firstName: Yup.string()
                .max(20)
                .required("Looks like you didn't enter your First Name."),
            lastName: Yup.string()
                .max(50)
                .required("Looks like you didn't enter your Last Name."),
            phone: Yup.string()
                .nullable()
                .notRequired()
                .when('phone', {
                    is: (value) => value?.length,
                    then: (rule) => 
                        rule.min(10, "Phone number is currently too short.")
                            .max(10)
                            .matches(
                            /^(\+\d{1,2}\s?)?1?\-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/,
                            "Invalid phone number format")        
            }),
            emailAddress: Yup.string()
                .max(55)
                .required("Looks like you didn't enter your Email Address."),
            comments: Yup.string()
                .max(100)
                .required("Looks like you didn't enter your Comments."),
            },[
                ['phone', 'phone']
        ]
    );

    const {
        register,
        handleSubmit,
        watch,
        formState: { errors },
        } = useForm({
            resolver: yupResolver(validationSchema),
            defaultValues: {
                firstName: "",
                lastName: "",
                phone: "",
                emailAddress: "",
                comments: "",
        },
    });

    const handleClose = props.handleClose;

    useEffect(() => {
        if (Object.keys(errors).length !== 0) {
            setIsIncompleteMsg(true);
        } else {
            setIsIncompleteMsg(false);
        }
    });

    function createBasicEmailBody(formData: any) {
        let body: string = "<table>";
        Object.keys(formData).forEach(key => {
            let label = // here I need to somehow get the label value
            body += this.addRow(label, formData[key].value);
        });
        body += "</table>";
        return body;
    }

    addRow(label: string, value: string) {
        let row = "";
        if (label && value) {
            row = "<tr><td>" + label + "</td><td>" + value + "</td></tr>";
        }
        return row;
    }

    return (
        <form
            className="w-100"
            onSubmit={handleSubmit(createBasicEmailBody)}
        >
        <div className="row">
            <div className="col-md-6 col-lg-4">
                <label htmlFor="">First Name (Required)</label>
            </div>
        </div>
        <div className="row popover-flex">
            <div className="col-md-6 col-lg-4">
                <input
                    style={{ 
                        backgroundColor: errors["firstName"] ? "#ffc7c7" : null,
                        border: errors["firstName"] ? "2px solid #ec3434" : "1px solid #ced4da",
                    }}
                    {...register("firstName")}
                    type="text"
                    className="form-control" 
                    data-label="First Name"
                />
            </div>
            {errors.firstName && <span className="popover-body">{errors.firstName.message}</span>}
        </div>
        <div className="row">
            <div className="col-md-6 col-lg-4">
                <label htmlFor="">Last Name (Required)</label>
            </div>
        </div>
        <div className="row popover-flex">
            <div className="col-md-6 col-lg-4">
                <input
                    style={{ 
                        backgroundColor: errors["lastName"] ? "#ffc7c7" : null,
                        border: errors["lastName"] ? "2px solid #ec3434" : "1px solid #ced4da"
                    }}
                    {...register("lastName")}
                    type="text"
                    className="form-control" 
                    data-label="Last Name"
                />
            </div>
            {errors.lastName && <span className="popover-body">{errors.lastName.message}</span>}
        </div>
        <div className="row">
            <div className="col-md-8 col-lg-6">
                <label htmlFor="">Phone Number (Optional)</label>
            </div>
        </div>
        <div className="row popover-flex">
            <div className="col-md-6 col-lg-4">
                <input
                    {...register("phone")}
                    type="text"
                    maxLength={14}
                    className="form-control" 
                    data-label="Phone Number"
                />
            </div>
            {errors.phone && <span className="popover-body">{errors.phone.message}</span>}
        </div>
        <div className="row">
            <div className="col-md-8 col-lg-6">
                <label htmlFor="">Email Address (Required)</label>
            </div>
        </div>
        <div className="row popover-flex">
            <div className="col-md-8 col-lg-6">
                <input
                    style={{ 
                        backgroundColor: errors["emailAddress"] ? "#ffc7c7" : null,
                        border: errors["emailAddress"] ? "2px solid #ec3434" : "1px solid #ced4da"
                    }}
                    {...register("emailAddress")}
                    className="form-control" 
                    data-label="Email Address"
                />
            </div>
            {errors.emailAddress && <span className="popover-body">{errors.emailAddress.message}</span>}
        </div>
        <div className="row">
            <div className="col-md-8 col-lg-6">
                <label htmlFor="">Comments (Required)</label>
            </div>
        </div>
        <div className="row popover-flex">
            <div className="col-md-8 col-lg-6">
                <textarea
                    style={{ 
                        backgroundColor: errors["comments"] ? "#ffc7c7" : null,
                        border: errors["comments"] ? "2px solid #ec3434" : "1px solid #ced4da"
                    }}
                    {...register("comments")}
                    className="form-control" 
                    data-label="Comments"
                ></textarea>
            </div>
            {errors.comments && <span className="popover-body">{errors.comments.message}</span>}
        </div>
        <div className="my-2">
            <input className="pm-button" type="submit" />
        </div>
        {/* <form-message 
            [message]="accessibilityContactFormMessage"
        >
        </form-message> */}
        {isIncompleteMsg && <div className="alert alert-danger font-rem-1 message-type-form my2">
        Your information isn&apos;t complete. Please check the required fields.
            </div>}
        </form>
    );
}
0

There are 0 answers