react hook form - change style to input - reactjs

I have validation that displays an error message, how to make the input border red when the form is incorrectly filled?
<div className={styles["form-group"]}>
<label>
Temat
</label>
<input
{...register("temat", { required: ErrorType.REQUIRED })}
className={styles.input}
/>
<p className={styles.invalid}>{errors?.temat?.message}</p>
</div>
how will i use it:
style={{ border: errors.temat?.message ? '1px solid red' : '' }}
the input turns red after clicking the submit button

Try to change mode on useForm. It works for me.
useForm({
mode: 'onChange',
...
})

Add a className for errors on the input element:
<div className={styles["form-group"]}>
<label>
Temat
</label>
<input
{...register("temat", { required: ErrorType.REQUIRED })}
className={`${styles.input} ${styles.errors}`}
/>
<p className={styles.invalid}>{errors?.temat?.message}</p>
</div>
or look use a library like classnames

A: You have to use conditional classes
className={ errors?.myInput?.message ? styles["error"] : "no-error" }
in this example I am using scss modules so i'll type the classNames as follow styles["myClassName"]
<input
id="accountReference"
className={
errors?.accountReference?.message ? styles["error"] : "no-error"
}
{...register("accountReference", {
required: "Account reference is required",
})}
/>
scss
input {
border-radius: 8px;
background-color: var(--100);
border: 2px solid var(--300);
padding: 8px 12px;
&.error {
border: 2px solid var(--error);
}
}
or you could do it in css
input {
border-radius: 8px;
background-color: black;
border: 2px solid black;
padding: 8px 12px;
}
input.error {
border: 2px solid red;
}

Related

Adding New Input Field using button in ReactJs

I am working on a project so I am trying to add a new input field after clicking the add(+) button in the form using react-Hooks. It would be very helpful if someone can figure this out so I can learn a new thing. Thankyou in advance.[React events handling link is added][1]
Here is the code of the form and css file
import Navbar from "./Navbar/Navbar";
import "./UserDetails.css";
function UserDetails() {
const [Info, setInfo] = useState({
username: "",
email: "",
bio: "",
positions: "",
});
const { username, email, bio, positions } = Info;
const onChange = (e) => setInfo({ ...Info, [e.target.name]: e.target.value });
const onSubmit = (e) => {
e.preventDefault();
console.log(Info);
};
return (
<div>
<Navbar />
<div className="full">
<h1 className="top">Edit Profile</h1>
<img
className="pic"
src="https://www.pngitem.com/pimgs/m/146-1468479_my-profile-icon-blank-profile-picture-circle-hd.png"
alt=""
></img>
<div className="inputs">
<form className="frms" onSubmit={(e) => onSubmit(e)}>
<input
className="insides"
type="text"
placeholder="Username"
name="username"
value={username}
onChange={(e) => onChange(e)}
></input>
<input
className="insides"
type="email"
placeholder="email"
name="email"
value={email}
onChange={(e) => onChange(e)}
></input>
<textarea
placeholder="Add Bio here..."
name="bio"
value={bio}
onChange={(e) => onChange(e)}
></textarea>
</form>
</div>
<div className="addbtn">
<input
className="insidesp"
type="text"
placeholder="positions held..."
name="positions"
value={positions}
onChange={(e) => onChange(e)}
></input>
<button>+</button>
<br></br>
<button className="savebtn">Save Changes</button>
</div>
</div>
</div>
);
}
export default UserDetails;
.full {
text-align: center;
border: 2px solid white;
margin: 0 auto;
padding-top: 1%;
width: 50%;
padding-bottom: 1%;
margin-top: 2%;
border-radius: 30px;
box-shadow: 5px 6px 5px 6px rgb(158, 170, 238);
}
.top {
color: rgb(88 99 161);
}
.pic {
height: 40%;
width: 30%;
}
.inputs input {
display: block;
width: 70%;
margin: 0 auto;
margin-top: 2%;
border: 2px solid rgb(88 99 161);
border-radius: 7px;
}
.inputs textarea {
display: block;
width: 70%;
margin: 0 auto;
margin-top: 2%;
border: 2px solid rgb(88 99 161);
border-radius: 7px;
}
.pic {
margin: 2%;
}
.savebtn {
margin-top: 2%;
background-color: rgb(88 99 161);
border: 2px solid rgb(158, 170, 238);
border-radius: 6px;
}
.addbtn {
display: inline;
}
.addbtn input {
margin-right: 1%;
width: 65%;
margin-top: 2%;
border: 2px solid rgb(88 99 161);
border-radius: 7px;
}
.addbtn button {
background-color: rgb(88 99 161);
border-radius: 6px;
border: 2px solid rgb(158, 170, 238);
}```
[1]: https://reactjs.org/docs/handling-events.html
Here is a great article that explains solution for your question step by step:
https://www.cluemediator.com/add-or-remove-input-fields-dynamically-with-reactjs

styled-components for input type password

how can I give styles for input type='password' in styled-components?
// export const Input = styled.input`
// width: 100%;
// height: 50px;
// border-radius: 4px;
// background-color: rgba(104, 105, 102, 0.1);
// border: 1px solid #354545;
// margin-top: 20px;
// outline: none;
// padding-left: 40px;
// color: white;
// font-size: 22px;
// `;
This should work. Unlike normal css, styled-components takes the attribute as props. You'll need to use props to style the elements conditionally.
export const Input = styled.input`
${props => props.type === 'password' && `
width: 100%;
height: 50px;
border-radius: 4px;
background-color: rgba(104, 105, 102, 0.1);
border: 1px solid #354545;
margin-top: 20px;
outline: none;
padding-left: 40px;
color: white;
font-size: 22px;
`}
`;
From styled-components documentation FAQ:
export const PasswordInput = styled.input.attrs(props => ({
// Every <PasswordInput /> should be type="password"
type: "password"
}))`
width: 100%;
height: 50px;
border-radius: 4px;
background-color: rgba(104, 105, 102, 0.1);
border: 1px solid #354545;
margin-top: 20px;
outline: none;
padding-left: 40px;
color: white;
font-size: 22px;`;
Both examples are a bit overkill for just styling purposes and can be easily avoided by using &[type="password"]
import styled from "styled-components";
export const Input = styled.input`
&[type="password"] {
border: 1px solid black;
background: red;
}
`;
export default function App() {
return (
<div>
<div>
<label htmlFor="username">Username</label>
<Input id="username" type="text" />
</div>
<div>
<label htmlFor="password">Password</label>
<Input type="password" />
</div>
</div>
);
}
Or, if you want to extend of of a base input component
import styled from "styled-components";
export const Input = styled.input`
border: 1px solid black;
`;
export const PasswordInput = styled(Input)`
&[type="password"] {
background: red;
}
`;
export default function App() {
return (
<div>
<div>
<label htmlFor="username">Username</label>
<Input id="username" type="text" />
</div>
<div>
<label htmlFor="password">Password</label>
<PasswordInput type="password" />
</div>
</div>
);
}

React: How to override input class in Material-UI Autocomplete

I am working on a React project, where I have been using Bootstrap for front-end. I have integrated Autocomplete library from Material-UI.
#ref: https://material-ui.com/components/autocomplete/
Problem: I am trying to integrate form-control class inside the input tag. But it's not working.
Tried:
<Autocomplete
id="combo-box-demo"
options={this.props.customers}
onChange={(_, value) => {
console.log(value);
}}
getOptionLabel={(option) => option.name}
style={{ width: 300 }}
renderInput={(params) => (
<div ref={params.InputProps.ref}>
<input
className="form-control"
placeholder="Search by client name"
type="text"
{...params.inputProps}
/>
</div>
)}
/>
Result
Expectation
I ended up having a solution with CSS. I copied the css code of .form-control class and put in combo-box-demo ID.
input#combo-box-demo {
display: block;
width: 100%;
padding: 0.375rem 0.75rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border-radius: 0.25rem;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

Styled components for nested html elements (React)

I am new to styled-components, and want to know how you would write it given the following html snippet:
<div class="segmentedControlContainer">
<input type="radio" name="segmentedControlExample" value="1" id="1" />
<label for="1"> One </label>
<input type="radio" name="segmentedControlExample" value="2" id="2" />
<label for="2"> Two </label>
<input type="radio" name="segmentedControlExample" value="3" id="3" />
<label for="3"> Three </label>
<div>
so far, I have defined
export const SegmentedControlWrapper = styled.div`
display: flex;
width: 100%;
position: relative;
z-index: 1;
user-select: none;
margin: 0 auto;
font-size: 16px;
border-radius: 3px;
border: solid 1px #bcbcbc
`
export const Input = styled.input`
display: none;
&:checked + label {
color: #fff;
background: #blah;
}
`
export const Label = styled.label`
flex: 1;
color: #blah;
padding: 15px;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
&:checked {
}
&:not(:last-child){
....
}
`
and use it in react as:
<SegmentedControlWrapper>
<Input />
<Label />
</SegmentedControlWrapper>
Most of this is correct, and I think the checked state isn't styled propelry. Any pointer would be appreciated. As I am confused with using &, >, etc.
Pass checked or not checked as props to style class. It will help to style in good way.
export const Input = styled.input
display: none;
&:checked + label {
color: #fff;
background: {$props => {this.props.checked ? "some" : "some"}}
}
<Input checked={this.state.checked}/>

why first two item is not working in react?

I have generated the following four buttons but the first two button (More button) is not working.
Here is the code:
BuildControls.js
import React from 'react';
import BuildControl from './BuildControl/BuildControl';
import classes from './BuildControls.css';
const controls = [
{label:'Salad', type:'salad'},
{label:'Bacon', type:'bacon'},
{label:'Cheese', type:'cheese'},
{label:'Meat', type:'meat'}
]
const buildControls =(props)=>(
<div className={classes.BuildControls}>
<p>Current Price: <strong> {props.price} </strong> BDT</p>
{controls.map(ctrl => (
<BuildControl
label ={ctrl.label}
key={ctrl.label}
addIngredient={()=>props.addIngredients(ctrl.type)}
removeIngredient={()=>props.removeIngredient(ctrl.type)}
disabled ={props.disabled[ctrl.type]}
/>
)
)}
<button
disabled={!props.purchaseAble}
className={classes.OrderButton}
onClick ={props.ordered}> ORDER NOW</button>
</div>
);
export default buildControls;
BuildControl.js
import React from 'react';
import classes from './BuildControl.css';
const builControl =(props)=>(
<div className={classes.BuildControl}>
<div className={classes.Label}> {props.label}</div>
<button className={classes.Less} onClick={props.removeIngredient} disabled ={props.disabled}> Less</button>
<button className={classes.More} onClick={props.addIngredient}> More</button>
</div>
);
export default builControl;
as all the button is being generated by loop problem should be same for all button. last two button is working perfectly but first two is not working. It kills my day. I don't know how to debug as I am new in react js. Any help ?
update:
When I remove {classes.BuildControls} from <div className={classes.BuildControls}> it works fine. and here is the css:
.BuildControls {
width: 100%;
background-color: #CF8F2E;
display: flex;
flex-flow: column;
align-items: center;
box-shadow: 0 2px 1px #ccc;
margin: auto;
padding: 10px 0;
}
.OrderButton {
background-color: #DAD735;
outline: none;
cursor: pointer;
border: 1px solid #966909;
color: #966909;
font-family: inherit;
font-size: 1.2em;
padding: 15px 30px;
box-shadow: 2px 2px 2px #966909;
}
.OrderButton:hover, .OrderButton:active {
background-color: #A0DB41;
border: 1px solid #966909;
color: #966909;
}
.OrderButton:disabled {
background-color: #C7C6C6;
cursor: not-allowed;
border: 1px solid #ccc;
color: #888888;
}
.OrderButton:not(:disabled) {
animation: enable 0.3s linear;
}
#keyframes enable {
0% {
transform: scale(1);
}
60% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
Strange! css causes problem in click event. Whats wrong in my code?
Without seeing the complete code, I would guess that addIngredients should be addIngredient in buildControls :
const buildControls =(props)=>(
<div className={classes.BuildControls}>
<p>Current Price: <strong> {props.price} </strong> BDT</p>
{controls.map(ctrl => (
<BuildControl
label ={ctrl.label}
key={ctrl.label}
addIngredient={()=>props.addIngredients(ctrl.type)}
// typo here -------------------------^
If that's not it, please post the addIngredient and removeIngredient methods, including where they are defined and how they are passed down.

Resources