React Hook Form - onSubmit does not works - reactjs

I have following component. I am making this based on react-hook-form documentation. Additionally I add styled components. But I find out problem with button. Submit button does not works. Nothing happen when I click on it
import styled from 'styled-components';
import { useForm } from "react-hook-form";
export const OrderDetailsForm = () => {
const { register, handleSubmit } = useForm();
const onSubmit = (data: any) => console.log(data);
return (
<OrderDetailsFormContainer>
<OrderForm onSubmit={handleSubmit(onSubmit)}>
<OrderDetailsFormContent>
<label>First Name</label>
<OrderDetailsFormInput {...register("firstName")} />
<label>Last Name</label>
<OrderDetailsFormInput {...register("lastName")} />
<label>Phone number</label>
<OrderDetailsFormInput {...register("phoneNumber")} />
<label>Email</label>
<OrderDetailsFormInput {...register("emailAddress")} />
<OrderDetailsFormHeader>Contact details</OrderDetailsFormHeader>
</OrderDetailsFormContent>
<OrderDetailsFormContent>
<label>Street</label>
<OrderDetailsFormInput {...register("street")} />
<label>House number</label>
<OrderDetailsFormInput {...register("houseNumber")} />
<label>City</label>
<OrderDetailsFormInput {...register("city")} />
<label>ZIP code</label>
<OrderDetailsFormInput {...register("zipCode")} />
<OrderDetailsFormHeader>Address</OrderDetailsFormHeader>
</OrderDetailsFormContent>
<input type='submit' />
</OrderForm>
</OrderDetailsFormContainer>
)
}
const OrderDetailsFormContainer = styled.main`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
`
const OrderForm = styled.article`
display: flex;
justify-content: center;
align-items: center;
width: 1200px;
`
const OrderDetailsFormContent = styled.section`
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
border: 1px solid #000;
box-sizing: border-box;
margin: 0 25px;
width: 50%;
padding: 30px 0 20px 20px;
position: relative;
`
const OrderDetailsFormInput = styled.input`
padding: 10px 40px;
margin: 15px 0;
`
const OrderDetailsFormHeader = styled.h1`
position: absolute;
top: -4%;
left: 4%;
margin: 0;
background-color: #fff;
padding: 0 20px;
font-size: 20px;
`
const Button = styled.button`
background-color: black;
color: white;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
`
Sorry for adding this, but it throws an error It looks like your post is mostly code; please add some more details. But I don't know what I can add more to this post.

Your issue is that you don't have a <form/> element.
Your <OrderForm/> component is rendering an <article/> element - this doesn't have an onSubmit prop, which is why the submission isn't working.
Change styled.article to styled.form here:
const OrderForm = styled.form`

const OrderForm = styled.article`
this line will generate an article element
and you know, article tag does not have onsubmit event.
change this line to:
const OrderForm = styled.form
good luck.

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

In styled-component, the button onClick event didn't working what I expected

After updating 'React-Router-Dom' in version6, I've studied functional components and styled-component. I am sorry if I asking such a stupid question.
I tried to make a button and when I click the button(onClick event) it changes the background color. So I tried to give pass the color in props and changing it when onClick event happened. When I check the developer tool, the color part change(#f4f4f4 or #f22).
So, I tried to setting setState and setState like this
export default function MarketPrice() {
const [color, setColor] = useState('#f4f4f4');
const onClick = () => {
color === '#f4f4f4' ? setColor('#fff') : setColor('#f4f4f4');
};
return (
<MarketPriceWrapper>
<TitleWrapper>
<MarketPriceTitle>시세</MarketPriceTitle>
<showAllSizes>
<AllSize>모든 사이즈</AllSize>
<FaRegArrowAltCircleDown />
</showAllSizes>
</TitleWrapper>
<salesGraphWrapper>
<Line data={data} options={options} />
</salesGraphWrapper>
<ButtonsWrapper>
<Button color={color} onClick={onClick}>
체결 거래
</Button>
<Button color={color} onClick={onClick}>
판매 입찰
</Button>
<Button color={color} onClick={onClick}>
구매 입찰
</Button>
</ButtonsWrapper>
</MarketPriceWrapper>
);
}
const MarketPriceWrapper = styled.div`
margin-top: 40px;
padding-left: 40px;
`;
const TitleWrapper = styled.div`
padding-top: 19px;
padding-bottom: 12px;
border-bottom: 1px solid #ebebeb;
`;
const MarketPriceTitle = styled.span`
padding-top: 4px;
display: inline-block;
line-height: 16px;
font-weight: bold;
color: #222;
`;
const AllSize = styled.span`
display: inline-block;
margin-right: 5px;
margin-left: 350px;
font-size: 18px;
`;
const ButtonsWrapper = styled.div`
display: flex;
justify-content: space-evenly;
margin-top: 40px;
border-radius: 10px;
background-color: #f4f4f4;
`;
const Button = styled.button`
display: block;
line-height: 16px;
padding: 7px 0 9px;
width: 150px;
font-size: 13px;
text-align: center;
border-radius: 8px;
border: none;
background-color: ${props => (props.onClick ? '#f4f4f4' : '#222')};
color: rgba(34, 34, 34, 0.8);
`;
Here is a button that I want to change the background color when I clicked it
Furthermore, is it okay with using the same component name as the button? I wonder if I click one of the buttons it changes the all-button background color.
It would be really appreciate your help!

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 to upload image with preview in react js

I have a reactjs application. I would like to know how to upload image with preview. Please advise.
you must read this mdn document about FileReader.
And then, based on your understand, you can apply like this.
export default () => {
const [preview, setPreview] = useState(null);
const fileHandler = evt => {
const f = evt.target.files[0];
if (f) {
const reader = new FileReader();
reader.onload = ({ target: { result } }) => {
setPreview(result);
};
reader.readAsDataURL(f); // you can read image file as DataURL like this.
} else {
setPreview(null);
}
};
return (
<div>
<input
type="file"
accept="image/*"
onChange={fileHandler}
/>
{ preview && <img src={preview} /> }
</div>);
}
The following illustrated code example is a part of my project.
As long as if you aren't following strict react pratices then this should work really well. You can change the styling as per your needs.
import React, { Component } from 'react';
import './App.css';
class App extends Component {
render() {
const imageHandler = () => {
const inpFile = document.getElementById('inpFile');
const previewContainer = document.getElementById('imagePreview');
const previewImage = previewContainer.querySelector('.image-preview__image');
const previewDefaultText = previewContainer.querySelector('.image-preview__default-text');
inpFile.addEventListener('change', function() {
const file = this.files[0];
if (file) {
const reader = new FileReader();
previewDefaultText.style.display = 'none';
previewImage.style.display = 'block';
reader.addEventListener('load', function() {
previewImage.setAttribute('src', this.result);
});
reader.readAsDataURL(file);
} else {
previewDefaultText.style.display = null;
previewImage.style.display = null;
previewImage.setAttribute('src', '');
}
});
};
return (
<div>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<div className="login">
<div className="reg-container">
<div className="profile-pic">
Add your Profile Picture:
<div className="add-picture">
<div className="image-preview" id="imagePreview">
<div className="card-image" />
<img alt="" className="image-preview__image" />
<span className="image-preview__default-text" />
</div>
<input
onClick={imageHandler}
type="file"
name="inpFile"
id="inpFile"
accept="image/*"
/>
<div className="label-holder">
<label className="image-upload" for="inpFile">
<i className="material-icons">add_photo_alternate</i>
Choose your Photo
</label>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
and obviously the styling file App.css
#import url('https://fonts.googleapis.com/css?family=Lato|Varela+Round&display=swap');
*{
margin: 0;
padding: 0;
}
.profile-pic {
font-family: 'Varela Round', sans-serif;
text-align: center;
padding: 1rem;
padding-top: 0;
padding-bottom: 0;
font-weight: bold;
font-size: 1.5rem;
}
/* ============================== */
.add-picture{
margin: auto;
font-size: 1rem;
display: flex;
text-align: center;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: 'Lato', sans-serif;
}
.image-preview{
width: 120px;
min-height: 150px;
border: 5px solid black;
margin-top: 15px;
border-radius: 15px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: #000;
outline: none;
z-index: ;
}
.image-preview__image{
display: none;
width: 100%;
height: 150px;
display:block;
object-fit: cover;
z-index: -11;
}
span{
/* background-image: url("../blank_user.webp"); */
width: 120px;
height: 150px;
background-size: cover;
background-position: center;
z-index: -9;
position: absolute;
border-radius: 15px;
outline: none;
}
#inpFile[type="file"]{
display:none;
margin-top: 20px;
}
.label-holder{
width: 200px;
height: 50px;
margin-top: 1rem;
}
.image-upload{
color: white;
background-color: black;
border: 1px solid #000;
display: inline-block;
padding: 6px 12px;
cursor: pointer;
font-family: 'Lato', sans-serif;
display: flex;
justify-content: center;
border-radius: 50px;
}
.description {
font-family: 'Varela Round', sans-serif;
text-align: center;
padding: 1rem;
padding-top: 0;
font-weight: bold;
font-size: 1.5rem;
}
.description textarea{
font-family: 'Lato', sans-serif;
font-size: 1rem;
background: none;
width: 350px;
height: 100px;
border: 2px solid black;
border-radius: 10px;
outline: none;
text-align: center;
}
#media screen and (max-width:550px){
.description textarea{
width: 260px;
}
}
Consider watching this Tutorial and other online article
you can also add the state management to the <input/>

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