Reputation: 873
I have InputField component which accepts various props like type,placeholder,value, etc. i am trying to create a form using InputField component. I can easily pass props from form but i cant save input values to my state. Here is my code.
InputField.js
import React, { useState } from "react";
const InputField = ({ value, label, placeholder, type, onChange }) => {
const handleChange = (e) => {
const { value } = e.target;
onChange(value);
};
return (
<div className="form-group">
{label && <label htmlFor="input-field">{label}</label>}
<input
type={type}
value={value}
className="form-control"
placeholder={placeholder}
onChange={handleChange}
/>
</div>
);
};
export default InputField;
AddProductForm.js
import React, { useState } from "react";
import { Form, Button } from "reactstrap";
import InputField from "../UI/InputField";
const AddProductForm = () => {
const [inputValue, setInputValue] = useState({ name: "", price: "" });
const { name, price } = inputValue;
const handleChange = (inputValue) => {
setInputValue({ name: inputValue, price: inputValue });
console.log(inputValue);
};
return (
<Form>
<InputField
type="text"
value={name}
placeholder="Product Name"
label="Name"
onChange={handleChange}
/>
<InputField
type="number"
value={price}
placeholder="Add Price"
label="Price"
onChange={handleChange}
/>
<Button color="primary">Add</Button>{" "}
<Button color="secondary">Cancel</Button>
</Form>
);
};
export default AddProductForm;
Upvotes: 9
Views: 32123
Reputation: 3217
Here's how to do it with TypeScript:
import { InputHTMLAttributes, forwardRef, ComponentProps } from "react";
import cn from "classnames";
type TInput = InputHTMLAttributes<HTMLInputElement> & {
label?: string;
wrapperClasses?: ComponentProps<"div">["className"];
};
export const Input = forwardRef<HTMLInputElement, TInput>(
({ wrapperClasses, label, className, id, name, value, ...rest }, ref) => {
return (
<div className={wrapperClasses}>
{label && (
<label htmlFor={id} className="pl-1 mb-1 inline-block font-semibold">
{label}
</label>
)}
<input
ref={ref}
id={id}
name={name}
value={value}
className={cn(
"border-2 border-primary bg-red transition h-12 px-5 rounded-md focus:outline-none w-full text-black text-lg",
className
)}
{...rest}
/>
</div>
);
}
);
Then we'd just use it like this:
<Input
ref={inputRef}
label="Username"
type="text"
placeholder="Enter your username"
wrapperClasses="mb-5"
value={username}
onChange={(e) => setUsername(e.target.value)}
classname="py-5" // <-- override default input css defined in Input component
/>
Upvotes: 0
Reputation: 19
tools react hooks,[mantine/core components]
[1]: https://mantine.dev/ yup schema and react hooks form for form validations
styled components
shared-input-text-filed.tsx
import { TextInput as customTextInput } from '@mantine/core';
import styled from 'styled-components';
type TextInputProps = {
key: string;
disabled?: boolean;
variant?: 'primary' | 'danger' | 'warning';
size?: 'sm' | 'lg';
className?: string;
icon?: any;
register: any;
required?: boolean;
error?: string;
};
const StyledTextInput = styled(customTextInput)``;
export const SharedTextFiled= (props: TextInputProps) => {
return (
<StyledTextInput
variant={props.variant}
type="text"
classNames={{
icon: 'border-r w-16 text-black h-full flex ',
withIcon: 'items-center',
input: 'indent-0',
}}
className={props.className}
disabled={props.disabled}
key={props.key}
required={props.required}
error={props.error}
icon={props.icon ? <>{props.icon}</> : ''}
{...props.register}
></StyledTextInput>
);
};
component-form.tsx
import { SharedTextInput} from '../../../shared/components/shared-text-input-filed';
<SharedTextInput
register={{ ...register('name') }}
className="mb-2"
icon={lang}
required={true}
error={errors?.name?.name?.message}
/>
Upvotes: 2
Reputation: 2289
Try passing from InputField
event
instead of value
.
Then in the handler
you can take the input name
and understand which field should be updated.
Of course, by first adding name
field for input
as shown below:
InputField.js
import React from "react";
const InputField = ({ value, label, name, placeholder, type, onChange }) => (
<div className="form-group">
{label && <label htmlFor="input-field">{label}</label>}
<input
type={type}
value={value}
name={name}
className="form-control"
placeholder={placeholder}
onChange={onChange}
/>
</div>
);
export default InputField;
AddProductForm.js
import React, { useState } from "react";
import InputField from "../UI/InputField";
const AddProductForm = () => {
const [inputValue, setInputValue] = useState({ name: "", price: "" });
const { name, price } = inputValue;
const handleChange = (e) => {
const { name, value } = e.target;
setInputValue((prev) => ({
...prev,
[name]: value,
}));
console.log(inputValue);
};
return (
<Form>
<InputField
type="text"
value={name}
placeholder="Product Name"
label="Name"
name="name"
onChange={handleChange}
/>
<InputField
type="number"
value={price}
placeholder="Add Price"
label="Price"
name="price"
onChange={handleChange}
/>
<Button color="primary">Add</Button>{" "}
<Button color="secondary">Cancel</Button>
</Form>
);
};
export default AddProductForm;
Upvotes: 28