Functional Component based simple form how to get values of input - javascript

I am new to ReactJS. Have been learning ReactJS since January. Came across a question on function based form, I am unable to get the values typed by the user. Please help.
This is the question...
A form template is given to you. Upon submitting, the information should be displayed in a list below (automatically sorted by last name) along with all the previous information that was entered.
I did an "alert({fname})", but it does not show the content of what the user entered....could you pleaes help me. I am just a beginner in ReactJS.
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
const style = {
table: {
borderCollapse: 'collapse'
},
tableCell: {
border: '1px solid gray',
margin: 0,
padding: '5px 10px',
width: 'max-content',
minWidth: '150px'
},
form: {
container: {
padding: '20px',
border: '1px solid #F0F8FF',
borderRadius: '15px',
width: 'max-content',
marginBottom: '40px'
},
inputs: {
marginBottom: '5px'
},
submitBtn: {
marginTop: '10px',
padding: '10px 15px',
border:'none',
backgroundColor: 'lightseagreen',
fontSize: '14px',
borderRadius: '5px'
}
}
}
function PhoneBookForm({ addEntryToPhoneBook }) {
const [fname,setFname] = useState("");
const [lname, setLname] = useState("");
const [uphone, setUphone] = useState("");
return (
<form onSubmit={e => {
e.preventDefault();
alert({fname});
//alert(${fname});
//console.log({fname});
}}
style={style.form.container}>
<label>First name:</label>
<br />
<input
style={style.form.inputs}
className='userFirstname'
name='userFirstname'
type='text'
placeholder='Coder'
onChange={e => setFname(e.target.value)}
value={fname}
/>
<br/>
<label>Last name:</label>
<br />
<input
style={style.form.inputs}
className='userLastname'
name='userLastname'
type='text'
placeholder='Byte'
onChange={e => setLname(e.target.value)}
value={lname}
/>
<br />
<label>Phone:</label>
<br />
<input
style={style.form.inputs}
className='userPhone'
name='userPhone'
type='text'
placeholder='8885559999'
onChange={e => setUphone(e.target.value)}
value={uphone}
/>
<br/>
<input
style={style.form.submitBtn}
className='submitButton'
type='submit'
value='Add User'
/>
</form>
)
}
function InformationTable(props) {
return (
<table style={style.table} className='informationTable'>
<thead>
<tr>
<th style={style.tableCell}>First name</th>
<th style={style.tableCell}>Last name</th>
<th style={style.tableCell}>Phone</th>
</tr>
</thead>
</table>
);
}
function App(props) {
return (
<section>
<PhoneBookForm />
<InformationTable />
</section>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
export default App;
Thank you,

try this
remove all you put inside onSubmit in the form,
take them out and put them into a function expression
like this:
const handleUserInput = (event) => {
event.preventDefault();
alert(fname);
alert(lname);
alert(uphone);
}
change form to this:
<Form onSubmit={handleUserInput} style={style.form.container}>
lastly, just being cautious, wrap all 'e' used with onChange with parenthesis
like this:
onChange={(e) => setFname(e.target.value)}
Goodluck with react js

You are doing everything right, looks like only one thing cause the problem,
alert({fname})
it should be
alert(fname)
without curly braces.
How to use curly braces you can read more detailed at jsx documentation

Related

How to delete all dynamically generated elements at once in a antd Form

If we have a component like this and we want to remove all generated elements at once (like reset the form elemets) how can i achive this by not removing elements from the DOM? The best approach should be to manipulate the "fields" directly, but how can we achive that?
import React, { useState, useContext } from 'react';
import { PlusOutlined, MinusOutlined } from '#ant-design/icons';
import { Button, Form } from 'antd';
const App = () => {
const [form] = Form.useForm();
const removeQuery = (event, key) => {
//How to remove all fields in fields?
};
return (
<Form
form={form}
name="dynamic_form_nest_item"
autoComplete="off"
preserve={false}
>
<Form.List name="filterattribute">
{(fields, { add, remove }) => (
<div>
<div>
<Form.Item>
<Button
type="dashed"
onClick={() => add()}
block
icon={<PlusOutlined />}
size="large"
>
Add Element
</Button>
</Form.Item>
</div>
<div className="greybg" style={{ padding: '6px 0px 8px' }}>
{fields.map(({ key, name, ...restField }) => (
<div
key={key}
style={{
display: 'flex',
marginTop: 0,
justifyContent: 'center',
}}
>
<MinusOutlined
key={key}
style={{ margin: '5px 15px -4px 0px', cursor: 'pointer' }}
onClick={(e) => {
remove(name);
removeQuery(e, key);
}}
/>
Element
</div>
))}
</div>
</div>
)}
</Form.List>
</Form>
);
};
export default App;
Here's a working example in Stackblitz:
https://stackblitz.com/edit/react-ts-a8fmfb?file=App.tsx

React - Material label not in right position in Textfield

I tried create the MUI textfield using same code in Codesandbox but everything works fine.
I tried to follow this post but not working
Can anyone give me some ideas of how to fix this issue?
const textfieldUseStyles = makeStyles((theme) => ({
root: {
"& > *": {
margin: "auto",
width: "100%",
},
},
}));
...
const textFieldClasses = textfieldUseStyles();
return (
<form className={textFieldClasses.root}>
<TextField
key="Confirmation Code"
variant="outlined"
id="email"
label="Post title"
name="email"
autoComplete="confirmation code"
value="123"
InputLabelProps={{ shrink: true }}
/>
</form>
)
Updated 1
After I added css class below, it changed to more good UI
.MuiInputLabel-outlined.MuiInputLabel-shrink {
transform: translate(0, -6px);
font-size: 12px;
margin: 0 14px;
background-color: white;
}
What I want is something like this, at least the label is in right position:
makeStyle is deprecated in Mui-v5 !!!
you can change textFiled border and other properties in various ways like:
the sx prop:
<TextField
sx={{ '& .MuiOutlinedInput-root': { borderRadius: '20px' } }} // change border form here
key="Confirmation Code"
variant="outlined"
id="email"
label="Post title"
name="email"
autoComplete="confirmation code"
value="123"
InputLabelProps={{ shrink: true }}
/>
Mui styled component way(using emotion)
import { styled } from '#mui/material/styles'
import TextField from '#mui/material/TextField'
export const StyledTextField = styled(TextField)(() => ({
'& .MuiInputBase-root': {
borderRadius: 20
}
}))

How to add a fixed button in the footer in material ui dialog?

I'm trying to create a dialog pop up for my react js app, when user clicks on button, dialog opens up. I have form with input fields in that dialog, after user fills out all inputs he can submit info by clicking "submit" button at the bottom of the dialog pop up. The problem is that I don't know how to stick submit button to the footer so even if there are 15+ inputs, user doesn't have to scroll all the way down to see "submit" button. I know that material ui has DialogActions for this purpose, but because dialog is in parent component, I don't have access to DialogActions from child. My code:
App.js (parent)
import React, { useState } from "react";
import Info from "./Info";
import Dialog from "#material-ui/core/Dialog";
import { DialogTitle } from "#material-ui/core";
import DialogContent from "#material-ui/core/DialogContent";
import DialogContentText from "#material-ui/core/DialogContentText";
import { DialogActions } from "#material-ui/core";
export default function App() {
const [open, setOpen] = useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<button onClick={handleClickOpen}>Click me to open dialog</button>
<Dialog
open={open}
aria-labelledby="responsive-dialog-title"
maxWidth="md"
setMaxWidth="md"
fullWidth={true}
>
<dialogContent>
<dialogTitle>
{" "}
<div>
<h4>Fill out the form</h4>
</div>
</dialogTitle>
<DialogContentText>
<Info />
</DialogContentText>
</dialogContent>
{/* <DialogActions>
<button id="responsive-dialog-title" onClick={handleClose}>
{" "}
Submit{" "}
</button>
</DialogActions> */}
</Dialog>{" "}
</div>
);
}
and Info.js (child) :
import React, { useState } from "react";
export default function Info() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const handleClickOpen = () => {
setOpen(true);
};
const handleSubmit = () => {
console.log(username);
console.log(password);
console.log(address);
};
return (
<form onSubmit={handleSubmit}>
<div
style={{
display: "flex",
flexDirection: "column",
width: "350px",
padding: "20px"
}}
>
<label> Username</label>
<input
value={username}
onChange={(e) => setUsername(e.target.value)}
type="text"
/>
</div>
<div
style={{
display: "flex",
flexDirection: "column",
width: "350px",
padding: "20px"
}}
>
<label> Password</label>
<input
value={password}
onChange={(e) => setPassword(e.target.value)}
type="password"
/>
</div>
<button> Submit</button>
</form>
);
}
codesandbox
Is there any way to make that "submit" button in Info.js displayed as DialogActions/ fixed to bottom? Any help and suggestion are greatly aprreciated.
Use the position: fixed property to achieve that. Your code would look like this:
<form onSubmit={handleSubmit}>
<div>
<div
style={{
display: "flex",
flexDirection: "column",
width: "350px",
padding: "20px"
}}
>
<label> Username</label>
<input
value={username}
onChange={(e) => setUsername(e.target.value)}
type="text"
/>
</div>
<div
style={{
display: "flex",
flexDirection: "column",
width: "350px",
padding: "20px"
}}
>
<label> Password</label>
<input
value={password}
onChange={(e) => setPassword(e.target.value)}
type="password"
/>
</div>
</div>
<div style={{ position: "fixed" }}>
<button> Submit</button>
<button> Cancel</button>
</div>
</form>
The scroll that the dialog has by default also had to be removed
<Dialog
open={open}
aria-labelledby="responsive-dialog-title"
maxWidth="md"
setMaxWidth="md"
fullWidth={true}
>
<div style={{ overflow: "hidden", height: "100%", width: "100%" }}>
<dialogTitle>
{" "}
<div>
<h4>Fill out the form</h4>
</div>
</dialogTitle>
<Info />
</div>
</Dialog>
This works, but the best thing to do is call the submit function from the parent, or the submit function exists in the parent and the inputs can be filled with context or a simple state

How do I populate a form field with data from redux?

I am having trouble trying to dynamically populate my "client edit form" with data from the corresponding listing in my "client table". As you can see, I have tried using "{this.onChange}", but to no avail.
import React, { Component } from "react";
import { Table, Container, Button } from "reactstrap";
import {
Modal,
ModalHeader,
ModalBody,
Form,
FormGroup,
Label,
Input,
Card,
CardTitle,
CardText,
CardDeck,
CardSubtitle,
CardBody,
} from "reactstrap";
import { connect } from "react-redux";
import { getClients, addClient, deleteClient } from "../actions/clientActions";
import PropTypes from "prop-types";
class ClientTable extends Component {
componentDidMount() {
this.props.getClients();
}
state = {
detailModal: false,
editModal: false,
name: "",
email: "",
number: "",
};
toggleEdit = () => {
this.setState({
editModal: !this.state.editModal,
});
};
toggleDetails = () => {
this.setState({
detailModal: !this.state.detailModal,
});
};
onDeleteClick = (id) => {
this.props.deleteClient(id);
};
renderClient = (clients, _id) => {
return (
<tr key={_id} timeout={500} classNames="fade">
<td>
<Button
className="remove-btn"
color="danger"
size="sm"
onClick={() => this.onDeleteClick(clients._id)}
>
×
</Button>
<Button
style={{ marginLeft: ".2rem" }}
className="add-btn"
outline
color="warning"
size="sm"
onClick={this.toggleEdit}
>
Edit
</Button>
<Button
style={{ marginLeft: ".3rem" }}
className="detail-btn"
outline
color="info"
size="sm"
onClick={this.toggleDetails}
>
Details
</Button>
</td>
<td>{clients.name}</td>
<td>{clients.email}</td>
<td>{clients.number}</td>
</tr>
);
};
render() {
const { clients } = this.props.client;
return (
<Container id="listContainer">
<Table
id="listTable"
className="table-striped table-bordered table-hover"
dark
>
<tr class="listRow">
<thead id="tableHeader">
<tr>
<th id="listActions">Actions</th>
<th id="listName">Name</th>
<th id="listEmail">Email</th>
<th id="listNumber">Number</th>
</tr>
</thead>
<tbody class="listRow">{clients.map(this.renderClient)}</tbody>
</tr>
<Modal isOpen={this.state.editModal} toggle={this.toggleEdit}>
<ModalHeader toggle={this.toggleEdit}> Edit Client </ModalHeader>
<ModalBody>
<Form onSubmit={this.onSubmit}>
<FormGroup>
<Label for="name"> Name </Label>
<Input
type="text"
name="name"
id="client"
placeholder="Add name"
onChange={this.onChange}
></Input>
<Label for="email"> Email </Label>
<Input
type="text"
name="email"
id="client"
placeholder="Add email"
onChange={this.onChange}
></Input>
<Label for="number"> Number </Label>
<Input
type="text"
name="number"
id="number"
placeholder="Add number"
onChange={this.onChange}
></Input>
<Button color="dark" style={{ marginTop: "2rem" }} block>
Submit Client Edit
</Button>
</FormGroup>
</Form>
</ModalBody>
</Modal>
<Modal isOpen={this.state.detailModal} toggle={this.toggleDetails}>
<ModalHeader toggle={this.toggleDetails}>
Client Details
</ModalHeader>
<CardDeck>
<Card></Card>
</CardDeck>
</Modal>
</Table>
</Container>
);
}
}
ClientTable.propTypes = {
getClients: PropTypes.func.isRequired,
client: PropTypes.object.isRequired,
};
const mapStateToProps = (state) => ({
client: state.client,
});
export default connect(mapStateToProps, {
getClients,
deleteClient,
addClient,
})(ClientTable);
How would I go about putting data from the redux store into the fields in my "Edit Client" form? If anyone has any ideas I would greatly appreciate it. This one is stumping me.
In general, by "controlling" the "value" property of an element. Instead of the element taking care of updating its displayed value natively - and triggering handlers only incidentally to what is visible - its value is passed in as the value from the store. The element then sets its value indirectly, through the reducer and store.
Clarification: the value of an html input element can be controlled using the jsx "value" prop. Pass in an onChange function (which you're already doing) and a value prop to create a typical controlled component.
<input value={state} onChange={onChange} />
https://reactjs.org/docs/forms.html#controlled-components

Open "choose file" dialog box on onclick of Raised Button Material ui

I have a Floating button (material ui) in my react project. I want to open "choose file" dialoge box whenever I click it. I am not getting any solution to do that. I tried doing this but didn't work. and I don't want to use jquery.
</div>
<input id="myInput" type="file" style="visibility:hidden" />
<FloatingActionButton className="floatingButton" backgroundColor='#293C8E' onClick ="$('#myInput').click();">
<ContentAdd />
</FloatingActionButton>
</div>
Can someone please tell me what exactly I need to do?
Basic example (does not include what to do with selected file):
<div>
<input id="myInput" type="file" ref={(ref) => this.upload = ref} style={{ display: 'none' }} />
<FloatingActionButton
className="floatingButton"
backgroundColor='#293C8E'
onClick={(e) => this.upload.click() }
>
<ContentAdd />
</FloatingActionButton>
</div>
So, your FloatingActionButton's onClick handler manually fires the click() handler of a hidden file upload control (input type="file"). A reference to the hidden upload control is obtained by putting a ref callback on it and storing that reference in "this.upload" (could also use DOM or jQuery to do that, but ref is preferred in React)
here is a working jsFiddle: https://jsfiddle.net/432yz8qg/58/
You can do the trick with the help of <label/> tag:
<label htmlFor='myInput'>
<input id="myInput" type="file" style={{visibility: 'hidden'}} />
<FloatingActionButton
className="floatingButton"
backgroundColor='#293C8E'
>
<ContentAdd />
</FloatingActionButton>
</label>
I solved this problem in a more React way than Jeff solution though my solution imply the use of multiple CSS rules.
I used a FlatButton with the props containerElement set to "label" :
const { FlatButton, SvgIcon, MuiThemeProvider, getMuiTheme } = MaterialUI;
class Example extends React.Component {
render() {
const buttonStyle = {
minWidth: '56px',
width: '56px',
minHeight: '56px',
height: '56px',
borderRadius: '28px',
};
return (
<div>
<FlatButton
containerElement="label"
backgroundColor='#293C8E'
style={buttonStyle}
>
<input type="file" style={{ display: 'none' }} />
</FlatButton>
</div>
);
}
}
const App = () => (
<MuiThemeProvider muiTheme={getMuiTheme() }>
<Example />
</MuiThemeProvider>
);
ReactDOM.render(
<App />,
document.getElementById('container')
);
<script src="https://unpkg.com/react#15.2.1/dist/react-with-addons.js"></script>
<script src="https://unpkg.com/react-dom#15.2.1/dist/react-dom.js"></script>
<script src="https://rawgit.com/nathanmarks/3f5196f5973e3ff7807f2bab4e603a37/raw/f409f3bf5902c211b358a3ebe7b6cd366da551e8/mui-umd.js"></script>
<div id="container"></div>
More details here : https://stackoverflow.com/a/36262984/2590861

Categories

Resources