Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
138 views
in Technique[技术] by (71.8m points)

reactjs - React fields validation

I have a validation for fields in the form:

const [orderForm, setOrderForm] = React.useState({
        title: {
            elementType: 'input',
            label: 'Title',
            elementConfig: {
                type: 'text',
                placeholder: 'Title'
            },
            value: '',
            validation: {
                required: true
            },
            valid: false,
            touched: false
        },
        price: {
            elementType: 'input',
            label: 'Price',
            elementConfig: {
                type: 'text',
                placeholder: 'Price'
            },
            value: '',
            validation: {
                required: true,
                isNumeric: true
            },
            valid: false,
            touched: false
        },
        category: {
            elementType: 'select',
            label: 'Select category',
            defaultValue: 'Select category',
            value: '',
            validation: {
                required: false
            },
            valid: false,
            touched: false
        },

        description: {
            elementType: 'textarea',
            label: 'Description',
            elementConfig: {
                type: 'text',
                placeholder: 'Description'
            },
            value: '',
            validation: {
                required: true
            },
            valid: false,
            touched: false
        },
    }); 

I faced the problem that I should add one more input field for image upload. I have this code for image upload (now it separated from my validation construction):

const [pickedImage, setPickedImage] = React.useState("");
const handleClick = () => { imageInput.current.click();};
const handleChange = () => {
            const file = imageInput.current.files[0];
            const reader = new FileReader();
            reader.onload = (event) => {
                setPickedImage(event.target.result);
            };
            if (file) {
                reader.readAsDataURL(file);
            }
        };
    
<input type="file" name="image" className="imageInput" ref={imageInput} onChange={handleChange} accept=".jpg,.png,.jpeg" />
<button className="button-empty" onClick={handleClick}>Choose Image</button>

Because it separated I do not understand how to make my button Add product make active only when user attached the image.

This is the whole code:

import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Header } from '../components/Header';
import { LeftMenu } from '../components/LeftMenu';
import * as categoriesActions from '../store/actions/categories';
import * as productsActions from '../store/actions/products';
import { updateObject, checkValidity } from '../utility/utility';
import Input from '../components/UI/Input/Input';
import Button from '../components/UI/Button/Button';
import { useHistory } from 'react-router-dom';

export const AddProduct = props => {
    const dispatch = useDispatch();
    let history = useHistory();
    const userId = '5fe99c69488a0f6307df5990';
    // const userId = useSelector(state => state.auth.userId);
    const categories = useSelector(state => state.categories.categories);


    React.useEffect(() => {
        dispatch(categoriesActions.fetchCategories());
    }, [dispatch]);

    const [pickedImage, setPickedImage] = React.useState("");
    const imageInput = React.useRef();

    const handleClick = () => {
        imageInput.current.click();
    };

    const handleChange = () => {
        const file = imageInput.current.files[0];
        const reader = new FileReader();
        reader.onload = (event) => {
            setPickedImage(event.target.result);
        };
        if (file) {
            reader.readAsDataURL(file);
        }
    };

    React.useEffect(() => {
        setOrderForm((oldValue) => ({
            ...oldValue,
            category: {
                ...oldValue.category,
                elementConfig:

                    categories.map((category) => (
                        <>
                            <option hidden>Choose category</option>
                            <option key={category._id} value={category._id}>
                                {category.title}
                            </option>
                        </>
                    )),
            }
        }));
    }, [categories])


    const [orderForm, setOrderForm] = React.useState({
        title: {
            elementType: 'input',
            label: 'Title',
            elementConfig: {
                type: 'text',
                placeholder: 'Title'
            },
            value: '',
            validation: {
                required: true
            },
            valid: false,
            touched: false
        },
        price: {
            elementType: 'input',
            label: 'Price',
            elementConfig: {
                type: 'text',
                placeholder: 'Price'
            },
            value: '',
            validation: {
                required: true,
                isNumeric: true
            },
            valid: false,
            touched: false
        },
        category: {
            elementType: 'select',
            label: 'Select category',
            defaultValue: 'Select category',
            value: '',
            validation: {
                required: false
            },
            valid: false,
            touched: false
        },

        description: {
            elementType: 'textarea',
            label: 'Description',
            elementConfig: {
                type: 'text',
                placeholder: 'Description'
            },
            value: '',
            validation: {
                required: true
            },
            valid: false,
            touched: false
        },
    });

    const [formIsValid, setFormIsValid] = React.useState(false);


    //Submit form data
    const orderHandler = event => {
        event.preventDefault();

        const formData = {};
        for (let formElementIdentifier in orderForm) {
            formData[formElementIdentifier] = orderForm[formElementIdentifier].value;
        }

        const product = {
            userId: userId,
            title: formData.title,
            price: formData.price,
            description: formData.description,
            category: formData.category,
            imageUrl: pickedImage
        };

        dispatch(productsActions.addProduct(product));
        history.push('/products');
    };

    //onChange Data
    const inputChangedHandler = (event, inputIdentifier) => {

        const updatedFormElement = updateObject(orderForm[inputIdentifier], {
            value: event.target.value,
            valid: checkValidity(
                event.target.value,
                orderForm[inputIdentifier].validation
            ),
            touched: true
        });


        const updatedOrderForm = updateObject(orderForm, {
            [inputIdentifier]: updatedFormElement
        });

        let formIsValid = true;

        for (let inputIdentifier in updatedOrderForm) {
            formIsValid = updatedOrderForm[inputIdentifier].valid && formIsValid;
        }
        setFormIsValid(formIsValid);
        setOrderForm(updatedOrderForm);

    };

    const formElementsArray = [];
    for (let key in orderForm) {
        formElementsArray.push({
            id: key,
            config: orderForm[key]
        });
    }
    let form = (
        <form class="row" onSubmit={orderHandler}>
            <div class="item--1-4 image-block">
                <div class="product-image-group">
                    {pickedImage ? (
                        <img onClick={handleClick} src={pickedImage} alt="preview" />
                    ) : (
                            <div onClick={handleClick} class="image-round-cover">
                                <ion-icon name="person-outline"></ion-icon>
                            </div>
                        )}

                    <input
                        type="file"
                        name="image"
                        className="imageInput"
                        ref={imageInput}
                        onChange={handleChange}
                        accept=".jpg,.png,.jpeg"
                    />
                    <button className="button-empty" onClick={handleClick}>
                        Choose Image
      </button>
                </div>
            </div>

            <div class="item--3-4">
                <div class="item-title">
                    <h3>Add product</h3>
                    <hr class="border-divider" />
                </div>
                {formElementsArray.map(formElement => (
                    <div class="group-fields">
                        < Input
                            key={formElement.id}
                            class={formElement.config.className}
                            ref={formElement.config.ref}
                            elementType={formElement.config.elementType}
                            elementConfig={formElement.config.elementConfig}
                            value={formElement.config.value}
                            invalid={!formElement.config.valid}
                            shouldValidate={formElement.config.validation}
                            touched={formElement.config.touched}
                            changed={event => inputChangedHandler(event, formElement.id)}
                        />
                    </div>
                ))}
                <div class="item-footer">
                    <Button btnType="Success" disabled={!formIsValid}>
                        Add product
      </Button>
                </div>
            </div>

        </form>
    );
    if (props.loading) {
        // form = <Spinner />;
    }
    return (
        <div class="wrapper">
            <Header />
            <article class="main">

                {form}

            </article>
            <LeftMenu />
        </div>
    );
};

Thank you for any support.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...