Adding New Input Field using button in ReactJs - 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

Related

How do I Setup a excel like filter using react-data-table-component

Been searching on how to make a excel like filter using react-data-table-component, and found something interesting, like Data Table filtering using react-data-table-component.
Unfortunately, the FilterComponent Component seems to be deprecated, since I can't find anything regarding it but broken links, which is weird for such a interesting feature.
My code is the following:
const columns = Properties.columns;
const getSubHeaderComponent = () => {
return (
<FilterComponent
onFilter={(e) => {
let newFilterText = e.target.value;
filteredItems = statements.filter(
(item) =>
item.name &&
item.name.toLowerCase().includes(newFilterText.toLowerCase())
);
this.setState({ filterText: newFilterText });
}}
onClear={handleClear}
filterText={filterText}
/>
);
};
return (
<div>
<div className="row justify-content-md-center statements-table">
<div className="col-md-10">
<DataTable
columns={columns}
data={statements}
customStyles={Properties.customStyles}
fixedHeader
fixedHeaderScrollHeight="47em"
pagination
subheader
subHeaderComponent={getSubHeaderComponent()}
paginationPerPage={100}
paginationRowsPerPageOptions={[100, 500, 1000]}
subHeader
noHeader
/>
</div>
</div>
Any suggestions?
FilterComponent could be something as simple as
const FilterComponent = ({ filterText, onFilter, onClear }) => (
<div>
<input
type="text"
value={filterText}
onChange={onFilter}
/>
<button type="button" onClick={onClear}>
X
</button>
</div>
);
However, I found following official implementation of FilterComponent on Examples/Filtering | React Data Table Components (also referred Button.js) if you need it like that.
const TextField = styled.input`
height: 32px;
width: 200px;
border-radius: 3px;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
border: 1px solid #e5e5e5;
padding: 0 32px 0 16px;
&:hover {
cursor: pointer;
}
`;
const ButtonStyle = styled.button`
background-color: #2979ff;
border: none;
color: white;
padding: 8px 32px 8px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
border-radius: 3px;
&:hover {
cursor: pointer;
}
`;
const Button = ({ children, ...rest }) => <ButtonStyle {...rest}>{children}</ButtonStyle>;
const ClearButton = styled(Button)`
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
height: 34px;
width: 32px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
`;
const FilterComponent = ({ filterText, onFilter, onClear }) => (
<>
<TextField
id="search"
type="text"
placeholder="Filter By Name"
aria-label="Search Input"
value={filterText}
onChange={onFilter}
/>
<ClearButton type="button" onClick={onClear}>
X
</ClearButton>
</>
);

react hook form - change style to input

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;
}

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>
);
}

How can I convert a function into a class in React?

I'm trying to create this sliding sign in /sign up portal but the original code was on Vanilla JS. The components seems unmounted on the Dom and the program is unable to find the Classlist by its id.I did few attempts on using Component did mount but it is throwing error, later I've found out that I am lacking understanding about Class vs function on react. componentDidMount() seems to be only for Classes. Now I cant seem to find a valid solution for this. Also I might forget, when should I really need to use Classes vs functions in rendering a component? How can I prevent calling an unmounted element in the DOM if I use function instead of class?
This is the raw Html,css,vanilla js code for the portal.
const signUpButton = document.getElementById('signUp');
const signInButton = document.getElementById('signIn');
const container = document.getElementById('container');
signUpButton.addEventListener('click', () => {
container.classList.add("right-panel-active");
});
signInButton.addEventListener('click', () => {
container.classList.remove("right-panel-active");
});
#import url('https://fonts.googleapis.com/css?family=Montserrat:400,800');
* {
box-sizing: border-box;
}
body {
background: #f6f5f7;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
font-family: 'Montserrat', sans-serif;
height: 100vh;
margin: -20px 0 50px;
}
h1 {
font-weight: bold;
margin: 0;
}
h2 {
text-align: center;
}
p {
font-size: 14px;
font-weight: 100;
line-height: 20px;
letter-spacing: 0.5px;
margin: 20px 0 30px;
}
span {
font-size: 12px;
}
a {
color: #333;
font-size: 14px;
text-decoration: none;
margin: 15px 0;
}
button {
border-radius: 20px;
border: 1px solid #FF4B2B;
background-color: #FF4B2B;
color: #FFFFFF;
font-size: 12px;
font-weight: bold;
padding: 12px 45px;
letter-spacing: 1px;
text-transform: uppercase;
transition: transform 80ms ease-in;
}
button:active {
transform: scale(0.95);
}
button:focus {
outline: none;
}
button.ghost {
background-color: transparent;
border-color: #FFFFFF;
}
form {
background-color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 50px;
height: 100%;
text-align: center;
}
input {
background-color: #eee;
border: none;
padding: 12px 15px;
margin: 8px 0;
width: 100%;
}
.container {
background-color: #fff;
border-radius: 10px;
box-shadow: 0 14px 28px rgba(0,0,0,0.25),
0 10px 10px rgba(0,0,0,0.22);
position: relative;
overflow: hidden;
width: 768px;
max-width: 100%;
min-height: 480px;
}
.form-container {
position: absolute;
top: 0;
height: 100%;
transition: all 0.6s ease-in-out;
}
.sign-in-container {
left: 0;
width: 50%;
z-index: 2;
}
.container.right-panel-active .sign-in-container {
transform: translateX(100%);
}
.sign-up-container {
left: 0;
width: 50%;
opacity: 0;
z-index: 1;
}
.container.right-panel-active .sign-up-container {
transform: translateX(100%);
opacity: 1;
z-index: 5;
animation: show 0.6s;
}
#keyframes show {
0%, 49.99% {
opacity: 0;
z-index: 1;
}
50%, 100% {
opacity: 1;
z-index: 5;
}
}
.overlay-container {
position: absolute;
top: 0;
left: 50%;
width: 50%;
height: 100%;
overflow: hidden;
transition: transform 0.6s ease-in-out;
z-index: 100;
}
.container.right-panel-active .overlay-container{
transform: translateX(-100%);
}
.overlay {
background: #FF416C;
background: -webkit-linear-gradient(to right, #FF4B2B, #FF416C);
background: linear-gradient(to right, #FF4B2B, #FF416C);
background-repeat: no-repeat;
background-size: cover;
background-position: 0 0;
color: #FFFFFF;
position: relative;
left: -100%;
height: 100%;
width: 200%;
transform: translateX(0);
transition: transform 0.6s ease-in-out;
}
.container.right-panel-active .overlay {
transform: translateX(50%);
}
.overlay-panel {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 40px;
text-align: center;
top: 0;
height: 100%;
width: 50%;
transform: translateX(0);
transition: transform 0.6s ease-in-out;
}
.overlay-left {
transform: translateX(-20%);
}
.container.right-panel-active .overlay-left {
transform: translateX(0);
}
.overlay-right {
right: 0;
transform: translateX(0);
}
.container.right-panel-active .overlay-right {
transform: translateX(20%);
}
.social-container {
margin: 20px 0;
}
.social-container a {
border: 1px solid #DDDDDD;
border-radius: 50%;
display: inline-flex;
justify-content: center;
align-items: center;
margin: 0 5px;
height: 40px;
width: 40px;
}
footer {
background-color: #222;
color: #fff;
font-size: 14px;
bottom: 0;
position: fixed;
left: 0;
right: 0;
text-align: center;
z-index: 999;
}
footer p {
margin: 10px 0;
}
footer i {
color: red;
}
footer a {
color: #3c97bf;
text-decoration: none;
}
<div class="container" id="container">
<div class="form-container sign-up-container">
<form action="#">
<h1>Create Account</h1>
<div class="social-container">
<i class="fab fa-facebook-f"></i>
<i class="fab fa-google-plus-g"></i>
<i class="fab fa-linkedin-in"></i>
</div>
<span>or use your email for registration</span>
<input type="text" placeholder="Name" />
<input type="email" placeholder="Email" />
<input type="password" placeholder="Password" />
<button>Sign Up</button>
</form>
</div>
<div class="form-container sign-in-container">
<form action="#">
<h1>Sign in</h1>
<div class="social-container">
<i class="fab fa-facebook-f"></i>
<i class="fab fa-google-plus-g"></i>
<i class="fab fa-linkedin-in"></i>
</div>
<span>or use your account</span>
<input type="email" placeholder="Email" />
<input type="password" placeholder="Password" />
Forgot your password?
<button>Sign In</button>
</form>
</div>
<div class="overlay-container">
<div class="overlay">
<div class="overlay-panel overlay-left">
<h1>Welcome Back!</h1>
<p>To keep connected with us please login with your personal info</p>
<button class="ghost" id="signIn">Sign In</button>
</div>
<div class="overlay-panel overlay-right">
<h1>Hello, Friend!</h1>
<p>Enter your personal details and start journey with us</p>
<button class="ghost" id="signUp">Sign Up</button>
</div>
</div>
</div>
</div>
And this is my current Login.js for my portal on a function.
import React, { useState } from 'react';
import axios from 'axios';
import { setUserSession } from './Utils/Common';
import './Login.css';
function Login(props) {
const [loading, setLoading] = useState(false);
const username = useFormInput('');
const password = useFormInput('');
const [error, setError] = useState(null);
const handleLogin = () => {
setError(null);
setLoading(true);
axios.post('http://localhost:4000/users/signin', { username: username.value, password: password.value }).then(response => {
console.log(username, password);
setLoading(false);
setUserSession(response.data.token, response.data.user);
props.history.push('/dashboard');
}).catch(error => {
setLoading(false);
if (error.response.status === 401) setError(error.response.data.message);
else setError("Something went wrong. Please try again later.");
});
}
const Signup = () => {
setError(null);
setLoading(true);
props.history.push('/Signup');
}
return (
<div className='login-wrapper' >
<div className='user-wrapper'>
<h1>Library Management System</h1>
<br />
<h1>Login</h1>
<br /><br />
<div className="user-details">
<h3>Username</h3>
<img src={userlogo} className="login-logo-user" />
<input type="text" {...username} autoComplete="new-password" />
</div>
<div className="user-details">
<h3>Password</h3>
<img src={passwordlogo} className="login-logo-password"/>
<input type="password" {...password} autoComplete="new-password" />
</div>
{error && <><small style={{ color: 'red' }}>{error}</small><br /></>}<br />
<input type="button" value={loading ? 'Loading...' : 'Login'} onClick={handleLogin} disabled={loading} id='buttons'/>
<input type="button" value={loading ? 'Loading...' : 'Signup'} onClick={Signup} id='buttons'/>
<div className="forgot-password">
<h5>Forgot Password? Click <span id="forgot-password">here</span>.</h5>
</div>
</div>
<div className='logo-wrapper'>
<div className="logo-main">
<img src={librarylogo} id="mainlogo"/>
<h2>Library Management System v1.0</h2>
</div>
</div>
</div>
);
}
const useFormInput = initialValue => {
const [value, setValue] = useState(initialValue);
const handleChange = e => {
setValue(e.target.value);
}
return {
value,
onChange: handleChange
}
}
export default Login;
Is this correct by the way?
I am trying to convert this as well?
from this function.
function login(props) {
const [loading, setLoading] = useState(false);
const username = useFormInput('');
const password = useFormInput('');
const [error, setError] = useState(null);
}
into a class:
class Login extends React.Component{
constructor(props) {
super(props);
this.state = {
loading, setLoading : false,
username : useFormInput(''),
password : useFormInput(''),
error, setError = null
}
}
}
I got it working now. Thanks for all the help.
class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
setLoading: false,
email: props.email,
password: props.password,
error: null,
setError: null
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount(){
const signUpButton = document.getElementById('signUp');
const signInButton = document.getElementById('signIn');
const container = document.getElementById('container');
if (container){
console.log('loaded');
signUpButton.addEventListener('click', () => {
container.classList.add("right-panel-active");
});
signInButton.addEventListener('click', () => {
container.classList.remove("right-panel-active");
});
}
}
handleChange(event) {
this.setState({
[event.target.type]: event.target.value
});
}
handleSubmitSignIn(event) {
// alert('A name was submitted: ' + this.state.email + this.state.password);
event.preventDefault();
console.log(this.state.email);
console.log(this.state.password);
}
handleSubmitSignUp(event) {
// alert('A name was submitted: ' + this.state.email + this.state.password);
event.preventDefault();
console.log(this.state.email);
console.log(this.state.password);
}
render() {
return (
<div className="container" id="container">
<div className="form-container sign-up-container">
<form onSubmit={this.handleSubmitSignUp}>
<h1>Create Account</h1>
<div className="social-container">
<i className="fab fa-facebook-f"></i>
<i className="fab fa-google-plus-g"></i>
<i className="fab fa-linkedin-in"></i>
</div>
<span>or use your email for registration</span>
<input type="text" placeholder="Name" autoComplete="new-name" />
<input type="email" placeholder="Email" autoComplete="new-email" />
<input type="password" placeholder="Password" autoComplete="new-password" />
<input type="department" placeholder="Department" autoComplete="new-name" />
<input type="year" placeholder="Year" autoComplete="new-email" />
<input type="schoolId" placeholder="School Id No." autoComplete="new-password" />
<button>Sign Up</button>
</form>
</div>
<div className="form-container sign-in-container">
<form onSubmit={this.handleSubmitSignIn}>
<h1>Sign in</h1>
<div className="social-container">
<i className="fab fa-facebook-f"></i>
<i className="fab fa-google-plus-g"></i>
<i className="fab fa-linkedin-in"></i>
</div>
<span>or use your account</span>
<input type="email" placeholder="Email" value={this.state.email} autoComplete='new-email' onChange={this.handleChange}/>
<input type="password" placeholder="Password" value={this.state.password} autoComplete='new-password' onChange={this.handleChange}/>
Forgot your password?
<button type='submit' >Sign In</button>
</form>
</div>
<div className="overlay-container">
<div className="overlay">
<div className="overlay-panel overlay-left">
<h1>Welcome Back!</h1>
<p>To keep connected with us please login with your personal info</p>
<button className="ghost" id="signIn">Sign In</button>
</div>
<div className="overlay-panel overlay-right">
<h1>Hello</h1>
<p>Enter your personal details and start journey with us</p>
<button className="ghost" id="signUp">Sign Up</button>
</div>
</div>
</div>
</div>
);
}
}
export default Login;

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}/>

Resources