Use value of an Input in a function - javascript

I'm a bit ashamed to write this topic because even if I got a HTML formation (4 years ago) I can't resolve my problem :
I can't use the value of an input type text in a function, this is my code:
import React from 'react'
//import db from '../../constants/FirebaseConfig'
class Account extends React.Component {
state = {
name: '',
content: ''
}
_formSubmit(e) {
e.preventDefault()
var name = document.getElementsByName('name')
console.log(name)
}
render(){
return(
<div className="container">
<br></br>
<h3 className="title">Account</h3>
<form id="form">
<br></br>
<label>Titre</label>
<input type="text" name="name" placeholder="Ici le nom de l'Article"/>
<br></br><br></br>
<label>Contenue</label>
<input type="text" name="content" placeholder="Ici le contenue de l'article"/>
<br></br><br></br>
<input type="button" value="suivant" onClick={(e) =>this._formSubmit(e)}/>
<br></br>
</form>
</div>
)
}
}
export default Account
After attempting to debug a few times I think the problem is with the var name object which is a NodeList<input> type.
My goal is to stock the 'name' and 'content' value in a firebase db.
Thank You

Two things:
getElementsByName is plural -- note the 's' in 'Elements'. So it doesn't just return one element, it returns a list, even if there's just one.
Since you are using React, you don't need to pull the value of the input that way at all. Instead, on the input itself, just add a value and onChange property, and then track the value being typed in there as state.
You already have a spot for them in your state, so just go ahead and use that. You'll track it live as they type, not just at form submission.
class Account extends React.Component {
state = {
name: '',
content: ''
}
_formSubmit(e) {
//just process your form _submission_ here
}
onChangeName = (e) => {
this.setState({
name: e.target.value
});
}
render(){
return(
<div className="container">
<br></br>
<h3 className="title">Account</h3>
<form id="form">
<br></br>
<label>Titre</label>
<input type="text" name="name" placeholder="Ici le nom de l'Article" value={this.state.name} onChange={this.onChangeName} />

Without suggesting any workaround but trying to make exactly what you posted work the way you're expecting it to, Here's what I figured out you were trying to do:
Your Problem:
_formSubmit(e) {
e.preventDefault()
var name = document.getElementsByName('name') //Get's a list of Elements with the given name
console.log(name) // This prints the list contained in name variable
}
The Solution:
_formSubmit(e) {
e.preventDefault()
// Assuming you're trying to print the values of all inputs
// First - Get all elements whose values you want to log, as per your initial code
var name = document.getElementsByName('name'); // returns ListNode<HTMLElement>
// Now loop through each input and print it's value to console
name.forEach(
function(input){
console.log(input.value); //Print the value of each input listed
}
);
}

On HandleChange function, it will automatically check the name where you have changed, and it will update the value
import React, { Component } from "react";
export default class App extends Component {
state = {
name: "",
content: "",
datas: []
};
handleChange = e => {
this.setState({
[e.target.name]: e.target.value
});
};
handleSubmit = e => {
e.preventDefault();
const data = {
name: this.state.name,
content: this.state.name
};
this.setState({
datas: [...this.state.datas, data],
name: "",
content: ""
});
};
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input
type="text"
name="name"
value={this.state.name}
onChange={this.handleChange}
placeholder="Ici le nom de l'Article"
/>
<input
type="text"
name="content"
value={this.state.content}
onChange={this.handleChange}
placeholder="Ici le nom de l'Article"
/>
<button>Submit</button>
</form>
<div>
{this.state.datas.map(item => {
return (
<div key={Math.random()}>
<h6>{Math.random()}</h6>
<h4>Name:{item.name}</h4>
<h4>Content:{item.content}</h4>
</div>
);
})}
</div>
</div>
);
}
}

Related

Uncaught TypeError - Getting errors after already defining state variable in React component constructor

I am getting the error: Uncaught TypeError: Cannot read properties of undefined (reading 'state') even though state is defined in the constructor of my React component. I get the error at the line where I set the value of the <input> to {this.state.deckName}
export class DeckForm extends React.Component {
constructor(props) {
super(props);
this.state = {
deckName: '',
deckList: ''
};
// Bind our event handler methods to this class
this.handleDeckNameChange = this.handleDeckNameChange.bind(this);
this.handleDeckListChange = this.handleDeckListChange.bind(this);
this.handleSubmission = this.handleSubmission.bind(this);
}
// Event handler method to update the state of the deckName each time a user types into the input form element
handleDeckNameChange(event) {
let typed = event.target.value;
this.setState({ deckName: typed });
}
// Event handler method to update the state of the deckList each time a user types into the textarea from element]
handleDeckListChange(event) {
let typed = event.target.value;
this.setState({ deckList: typed });
}
// Event handler method to handle validation of deckName and deckList
handleSubmission(event) {
console.log(`${this.state.deckName}`);
console.log(`${this.state.deckList}`)
}
render() {
return (
<form className='was-validated'>
<this.DeckName />
<this.DeckList />
<button type='submit' className='btn-lg btn-warning mt-3'>Create</button>
</form>
);
}
DeckName() {
return (
<div className='form-group mb-3'>
<input
value={this.state.deckName} /* ERROR HERE */
onChange={this.handleDeckNameChange}
type='text'
placeholder='Deck name'
className='form-control'
required
/>
</div>
);
}
DeckList() {
let format = 'EXACT CARD NAME 1\nPot of Greed 3\nChange of Heart 3\nGraceful Charity 3'
return (
<div className='form-group'>
<textarea
value={this.state.deckList}
onChange={this.handleDeckListChange}
className='form-control'
rows='15'
required
>
{format}
</textarea>
</div>
);
}
}
Use below code it's working for me
https://codesandbox.io/s/weathered-water-jm1ydv?file=/src/App.js
DeckName() {
return (
<div className="form-group mb-3">
<input
value={this?.state.deckName} /* ERROR HERE */
onChange={this?.handleDeckNameChange}
type="text"
placeholder="Deck name"
className="form-control"
required
/>
</div>
);
}
DeckList() {
let format =
"EXACT CARD NAME 1\nPot of Greed 3\nChange of Heart 3\nGraceful Charity 3";
return (
<div className="form-group">
<textarea
value={this?.state.deckList}
onChange={this?.handleDeckListChange}
className="form-control"
rows="15"
required
>
{format}
</textarea>
</div>
);
}
You can use es6 function to return components which exist outside of parent rather than using method,change only this part of code:
1.instead of DeckName(){...}use DeckName =()=>{....}
2.instead of DeckList(){...}use DeckList =()=>{....}
Full modified code:
import React, { Component } from "react";
export class DeckForm extends Component {
constructor(props) {
super(props);
this.state = { deckName: "", deckList: "" };
// Bind our event handler methods to this class
this.handleDeckNameChange = this.handleDeckNameChange.bind(this);
this.handleDeckListChange = this.handleDeckListChange.bind(this);
this.handleSubmission = this.handleSubmission.bind(this);
}
// Event handler method to update the state of the deckName each time a user types into the input form element
handleDeckNameChange(event) {
let typed = event.target.value;
this.setState({ deckName: typed });
}
// Event handler method to update the state of the deckList each time a user types into the textarea from element]
handleDeckListChange(event) {
let typed = event.target.value;
console.log(typed);
this.setState({ deckList: typed });
}
// Event handler method to handle validation of deckName and deckList
handleSubmission(event) {
console.log(`${this.state.deckName}`);
console.log(`${this.state.deckList}`);
}
render() {
return (
<form className="was-validated">
<this.DeckName />
<this.DeckList />
<button type="submit" className="btn-lg btn-warning mt-3">
Create
</button>
</form>
);
}
DeckName = () => {
return (
<div className="form-group mb-3">
<input
value={this.state.deckName}
onChange={this.handleDeckNameChange}
type="text"
placeholder="Deck name"
className="form-control"
required
/>
</div>
);
};
DeckList = () => {
let format =
"EXACT CARD NAME 1\nPot of Greed 3\nChange of Heart 3\nGraceful Charity 3";
return (
<div className="form-group">
<textarea
value={this.state.deckList}
onChange={this.handleDeckListChange}
className="form-control"
rows="15"
required
>
{format}
</textarea>
</div>
);
};
}
Live Demo:
https://codesandbox.io/s/brave-hill-l0eknx?file=/src/DeckForm.js:0-2091
Another way to solve the issue is defining DeckName() method using arrow function. Here's a code snippet I tried with react 17.0.2 which worked perfectly fine for me.
It's always recommended to use arrow function to define methods in class based components, since arrow function inherit "this" from the block its called from, so you also don't have to do .bind(this) whenever you call methods.
JSX
import React, { Component } from 'react'
class Test extends Component {
constructor(props) {
super(props);
this.state = {
deckName: '',
deckList: ''
};
}
DeckName = () => {
return (
<div className='form-group mb-3'>
<input
value={this.state.deckName} /* ERROR HERE */
onChange={this.handleDeckNameChange}
type='text'
placeholder='Deck name'
className='form-control'
required
/>
</div>
);
}
render() {
return (
<form className='was-validated'>
<this.DeckName />
<button type='submit' className='btn-lg btn-warning mt-3'>Create</button>
</form>
);
}
}
export default Test

react router redirect to self/same page

How to redirect in react router in self page. e.g I have a component ProfileUpdate it updates name & stores to backend. After successful update I want to redirect to same page but it's not working. Here is a sample code.
class ProfileUpdate extends Component {
constructor() {
super();
this.state = {
name: ''
};
}
onSubmit(e) {
e.preventDefault();
this.props.history.replace('/');
}
onChange(e) {
const name = e.target.value;
this.setState(() => ({
name
}))
}
render() {
return (
<form onSubmit={this.onSubmit}>
<div>
<h4>Display Name:</h4>
<div>
<input name='displayName' placeholder='Display name' type='text' value={this.state.name} onChange={this.onChange} />
</div>
</div>
<div>
<button type='submit'>Update</button>
</div>
</form>
);
}
}
Expected behaviour if I update name then click submit it will replace the route/redirect & name input should be empty.
But when I choose a different path to replace it works. e.g this.props.history.replace('/users') it works. But here this.props.history.replace('/'); it doesn't work.

Unable to type into my second field on a React form. Why could this be happening?

I am somewhat new to react, and I am having trouble recognizing whats causing my form to be broken. The submit button works fine and the name adds fine, but i cannot type into my price text-field for some reason. when adding items to the list, the dollar sign for price is adding, but i cant type anything into the price field.
import React, { Component } from 'react';
class ItemForm extends Component {
state = { name: '', price: ''}
handleChange = (e) => {
const { name, value } = e.target
this.setState({ [name]: value })
}
handleSubmit = (e) => {
//stop page from reloading
e.preventDefault();
//add item to groceries array
const { addItem } = this.props
addItem(this.state.name, this.state.price)
// this.props.addItem(this.state.price)
//clear form on submit
this.setState({name: '', price: ''})
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
required
placeholder='add Grocery Item'
name="name"
value={this.state.name}
onChange={this.handleChange}
/>
<br />
<input
placeholder='add price (optional)'
name="price"
value={this.state.price}
onChange={this.handleChange}
/>
<br />
<input class = "btn btn-primary" type = "submit" value =
"Add" />
</form>
)
}
}
export default ItemForm;
I think you accidentally put price="price" instead of name="price"

Creating a form in React that saves data

I am trying to create a customer details form in react (currently using react-json-form) where I can reuse the values in the inputs to create a saved file that the app can refer to. I have created the form and can output the results but I am unsure how to save the input values for future use or call them back once they are saved.
If anyone has any suggestions or examples of a form that does this then I would be greatly appreciative.
My code is as follows:
import React, { Component } from 'react';
import JSONTree from 'react-json-tree';
import { BasicForm as Form, Nest, createInput } from 'react-json-form';
const Input = createInput()(props => <input type="text" {...props} />);
const UserFields = () => (
<section>
<h3>User</h3>
<div>Name: <Input path="name" /></div>
<div>Email: <Input path="email" /></div>
</section>
);
export default class ExampleForm extends Component {
state = { data: {} };
updateData = data => this.setState({ data });
render() {
return (
<Form onSubmit={this.updateData}>
<Nest path="user">
<UserFields />
</Nest>
<button type="submit">Submit</button>
<JSONTree data={this.state.data} shouldExpandNode={() => true} />
</Form>
);
}
}
A more simple solution would be to use a form, like a semanti-ui-react form, store the information to the state onChange, then convert the info to JSON for storage.
import { Form, Button } from 'semantic-ui-react'
export default class App extends Component {
constructor() {
super()
this.state = {
name: "",
email: ""
}
}
handleChange = (e, {name, value}) => {
console.log(name, value)
this.setState({[name]: value})
}
render() {
return (
<div>
<Form onSubmit={this.sendDataSomewhere}>
<Form.Field>
<Form.Input name="name" value={this.state.name} onChange={this.handleChange}/>
</Form.Field>
<Form.Field>
<Form.Input name="email" value={this.state.email} onChange={this.handleChange}/>
</Form.Field>
<Button type="submit">Submit</Button>
</Form>
</div>
)
}
}
I use a dynamic method of receiving the input from different fields using the name and val attributes. The values captured in state are then accessible by this.state.whatever
Hope this helped

react-bootstrap: clear element value

I'm trying to clear my input fields after an onClick event.
I'm using react-bootstrap library and while there is a getValue() method, there is not setValue(value) method.
I've stumbled upon this discussion .
I did not fully understand what they are suggesting in order to simply clean a form after submission.
After all, If I would use a simple HTML <input> instead of react-bootstrap I could grab the node via element ref and set it's value to be empty string or something.
What is considered a react way to clean my react-bootstrap <Input /> element?
Store the state in your React component, set the element value via props, get the element value via event callbacks. Here is an example:
Here is an example taken directly from their documentation. I just added a clearInput() method to show you you can clear the input by just updating the state of your component. This will trigger a re-render which will cause the input value to update.
const ExampleInput = React.createClass({
getInitialState() {
return {
value: ''
};
},
validationState() {
let length = this.state.value.length;
if (length > 10) return 'success';
else if (length > 5) return 'warning';
else if (length > 0) return 'error';
},
handleChange() {
// This could also be done using ReactLink:
// http://facebook.github.io/react/docs/two-way-binding-helpers.html
this.setState({
value: this.refs.input.getValue()
});
},
// Example of how you can clear the input by just updating your state
clearInput() {
this.setState({ value: "" });
},
render() {
return (
<Input
type="text"
value={this.state.value}
placeholder="Enter text"
label="Working example with validation"
help="Validation is based on string length."
bsStyle={this.validationState()}
hasFeedback
ref="input"
groupClassName="group-class"
labelClassName="label-class"
onChange={this.handleChange} />
);
}
});
For what I'm doing at the moment, I didn't really think it was necessary to control the Input component's value through setState/Flux (aka I didn't want to deal with all the boilerplate)...so here's a gist of what I did. Hopefully the React gods forgive me.
import React from 'react';
import { Button, Input } from 'react-bootstrap';
export class BootstrapForm extends React.Component {
constructor() {
super();
this.clearForm = this.clearForm.bind(this);
this.handleSave = this.handleSave.bind(this);
}
clearForm() {
const fields = ['firstName', 'lastName', 'email'];
fields.map(field => {
this.refs[field].refs['input'].value = '';
});
}
handleSubmit() {
// Handle submitting the form
}
render() {
return (
<div>
<form>
<div>
<Input
ref='firstName'
type='text'
label='First Name'
placeholder='Enter First Name'
/>
<Input
ref='lastName'
type='text'
label='Last Name'
placeholder='Enter Last Name'
/>
<Input
ref='email'
type='email'
label='E-Mail'
placeholder='Enter Email Address'
/>
<div>
<Button bsStyle={'success'} onClick={this.handleSubmit}>Submit</Button>
<Button onClick={this.clearForm}>Clear Form</Button>
</div>
</div>
</form>
</div>
);
}
}
If you use FormControl as an input, and you want to use ref to change/get value from it, you use inputRef instead of ref
<FormControl inputRef={input => this.inputText = input} .../>
and use this to get/change its value:
this.inputText.value
This worked for me in case someone else is looking for an answer :D
You can access the values of react-bootstrap by using
console.log(e.target.form.elements.fooBar.value)
You can clear them by using
e.target.form.elements.fooBar.value = ""
import React from 'react';
import {Button, Form} from 'react-bootstrap';
export default function Example(props) {
const handleSubmit = (e) => {
// Handle submitting the form
}
const resetSearch = (e) => {
e.preventDefault();
e.target.form.elements.fooBar.value = ""
}
render() {
return (
<Form onSubmit={handleSubmit} onReset={resetSearch} >
<Form.Control type="input" name="fooBar" />
<Button type="submit"> Submit </Button>
<Button onClick={resetSearch} type="submit" > Reset </Button>
</Form>
);
}
}
You can also just use ReactDOM:
<FormControl
componentClass="select"
ref="sStrike">
<option value="-">Select…</option>
<option value="1">1</option>
<option value="2">2</option>
</FormControl>
Now a different FormControl fires an onChange={handleChange} and in that handler you can just id the ref and set to the default value:
ReactDOM.findDOMNode(this.refs.sStrike).value = '-';
and that will set the select box to the 'default' value.
Just add a button in-side form with the attribute type="reset"
<Button variant="primary" type="reset">Reset</Button>

Categories