constructor(props) {
super(props);
this.submitQA = this.submitQA.bind(this);
this.onSearchChange = this.onSearchChange.bind(this);
this.isSearched = this.isSearched.bind(this);
this.answerSubmitted = this.answerSubmitted.bind(this);
this.reset = this.reset.bind(this);
this.state = {
answers: [],
answer: '',
searchTerm: '',
}
}
reset() {
console.log("reset");
}
render() {
const answer = true;
return (
<div className="App">
<div className="center">
<form >
Search: <input type="text" onChange={this.onSearchChange} /><br/>
</form>
<form onSubmit={this.submitQA}>
Q & A:
<input type="text" placeholder=" Course/Q/A"/>
<button type="submit"> Submit </button>
</form>
<span>{basicFormat}</span>
</div>
{
this.state.answers.filter(this.isSearched(this.state.searchTerm)).map((item) => {
return (
if(answer) {
this.reset;
}
<div>
<form onSubmit={this.answerSubmitted}>
<text> {item} </text>
<input type="text" placeholder="answer the question"/>
</form>
</div>
)
})
}
</div>
);
}
Why can't I use any logic in this render method? Keeps giving me unexpected token. Do not see anything wrong with it. Looked at some tutorials and they are doing the exact same thing but why is mine throwing me an error?
You've included a Javascript if statement inside the return, mixed with the JSX.
Quoting the React documentation:
if statements and for loops are not expressions in JavaScript, so they can't be used in JSX directly. Instead, you can put these in the surrounding code.
To fix the unexpected token error, move the if statement before the return:
{
this.state.answers.filter(this.isSearched(this.state.searchTerm)).map((item) => {
if(answer) {
this.reset();
}
return (
<div>
<form onSubmit={this.answerSubmitted}>
<text> {item} </text>
<input type="text" placeholder="answer the question"/>
</form>
</div>
)
})
}
I would also recommend that you perform the mapping before the return in the render function. That way, the rendering is more clearly separated from the data manipulation.
render() {
const answer = true;
const answerForms = this.state.answers
.filter(this.isSearched(this.state.searchTerm))
.map((item) => {
if (answer) {
this.reset()
}
return (
<div>
<form onSubmit={this.answerSubmitted}>
<text> {item} </text>
<input type="text" placeholder="answer the question" />
</form>
</div>
)
})
return (
<div className="App">
<div className="center">
<form >
Search: <input type="text" onChange={this.onSearchChange} /><br />
</form>
<form onSubmit={this.submitQA}>
Q & A:
<input type="text" placeholder=" Course/Q/A" />
<button type="submit"> Submit </button>
</form>
<span>{basicFormat}</span>
</div>
{answerForms}
</div>
)
}
Related
I've made a form in ReactJS with one text input and when it submits I want to get its value and put it into a variable. But when I console.log() it returns as undefined. How do I fix this? Here is my code.
class App extends Component {
state = {
todoTitle: ""
};
render() {
return (
<div>
<center>
<form
onSubmit={(event) => {
event.preventDefault();
this.setState(todoTitle: event.target.value,);
console.log(this.state.todoTitle); // Returns "undefined"
}}
>
<input
type="text"
autocomplete="off"
class="form-control"
name="todoInput"
placeholder="Enter todo"
style={{ width: "400px", height: "50px" }}
/>
<input
type="submit"
value="Submit"
id="submitButton"
></input>
</form>
</center>
}
}
}
You need to either make a controlled input or useRef for un-controlled input for the React to keep track of your todoTitle state.
To make a controlled input, you will need to use onChange event and a value={this.state.todoTitle} property.
Also on your form, it is best to add an onSubmit event. There is however an option to set the submit on the form submit button also. In that case we need to use onClick={this.handleSubmit} as follows <input type="submit" value="Submit" id="submitButton" onClick={this.handleSubmit} />.
The below code will work for you:
class Form extends React.Component {
state = {
todoTitle: "",
};
handleSubmit = (e) => {
e.preventDefault();
console.log(this.state.todoTitle);
};
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input
type="text"
autocomplete="off"
class="form-control"
name="todoInput"
placeholder="Enter todo"
style={{ width: "400px", height: "50px" }}
value={this.state.todoTitle}
onChange={(e) => this.setState({ todoTitle: e.target.value })}
/>
<input type="submit" value="Submit" id="submitButton" />
</form>
</div>
);
}
}
You can modify your app a bit to get the value on onChange of input textfield, and then store it in the array in case of below example:
export default class App extends React.Component {
state = {
todoTitle: "",
todoList: []
};
render() {
return (
<div>
<center>
<form
onSubmit={event => {
event.preventDefault();
this.setState(
{
todoList: [...this.state.todoList, this.state.todoTitle]
},
() => {
console.log(this.state.todoList);
}
);
}}
>
<input
type="text"
autocomplete="off"
class="form-control"
name="todoInput"
placeholder="Enter todo"
onChange={event => {
this.setState({ todoTitle: event.target.value });
console.log(event.target.value);
}}
style={{ width: "400px", height: "50px" }}
/>
<input type="submit" value="Submit" id="submitButton" />
</form>
</center>
</div>
);
}
}
Full app here: Stackblitz
There are a few other errors with your code, but I will just answer your question.
setState triggers a re-render, so your state isn't available to log until the next time it runs. You can just log what you put in setState.
console.log(event.target.value);
This question has more info.
setState doesn't update the state immediately
Also, you can do a callback.
this.setState({ todoTitle: event.target.value }, () =>
console.log(this.state.todoTitle)
);
Try this:
class App extends React.Component {
constructor(props) {
super(props);
this.state = { todoTitle: "" };
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
event.preventDefault();
this.setState({ todoTitle: event.target.value });
}
handleSubmit(event) {
event.preventDefault();
console.log(this.state.todoTitle);
}
render() {
return (
<div>
<center>
<form onSubmit={this.handleSubmit}>
<input
type="text"
autocomplete="off"
class="form-control"
name="todoInput"
placeholder="Enter todo"
style={{ width: "400px", height: "50px" }}
onChange={this.handleChange}
/>
<input type="submit" value="Submit" id="submitButton" />
</form>
</center>
</div>
);
}
}
This will change the state on input changes and then logs on submit the state. An alternative would be to just get the input element and its value via getElementById or something similar in React.
Your code was also not very well formatted and a lot of closing tags missed.
Read more here:
Get form data in ReactJS
return (
{jobstate.jobs.map((data,i) =>{
<form>
<input type="text" placeholder="Post a comment" onChange={(e) => jobcmthandler(e,data._id,i) } />
<button type="button" onClick={postcmt} >Send</button>
</form>
})}
)
I generate dynamic HTML using the map function and I want to disabled button if text null for induvial form and also how to get text value on button click in react js
I can't really see why you'd want to do this but here you go (example):
import React, { useState } from "react";
export default function App() {
return ["Name", "Age"].map((label) => <Form label={label} />);
}
function Form({ label }) {
const [readValue, writeValue] = useState("");
return (
<form>
<label>{label}</label>
<input
type="text"
placeholder="Post a comment"
onChange={(e) => writeValue(e.target.value)}
value={readValue}
/>
<button
type="button"
onClick={() => console.log("Submit")}
disabled={readValue === ""}
>
Send
</button>
</form>
);
}
I am created a dynamic form in react.js but i can not type anything value in input because onchnage function not working i don't know why i tried a lot of times but i am getting failed and adding form and deleting form is working all right only input value not working here is my code and codesandbox link https://codesandbox.io/s/reactdynamicform-02cho .
import React, { Component } from "react";
import "bootstrap/dist/css/bootstrap.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
inputFields: [
{
firstName: "",
lastName: ""
}
]
};
}
handleAddFields = () => {
const values = this.state.inputFields;
values.push({ firstName: "", lastName: "" });
this.setState({
values
});
};
handleRemoveFields = index => {
const values = this.state.inputFields;
values.splice(index, 1);
this.setState({
values
});
};
async onChange(e, index) {
if (
["firstName","lastName"].includes(e.target.name)
) {
let cats = [...this.state.inputFields];
cats[index][e.target.name] = e.target.value;
await this.setState({
cats
});
}else{
this.setState({ [e.target.name]: e.target.value.toUpperCase() });
}
console.log(this.state.inputFields);
}
handleSubmit = e => {
e.preventDefault();
console.log("inputFields", this.state.inputFields);
};
render() {
return (
<>
<h1>Dynamic Form Fields in React</h1>
<form onSubmit={this.handleSubmit.bind(this)}>
<div className="form-row">
{this.state.inputFields.map((inputField, index) => (
<div key={`${inputField}~${index}`}>
<div className="form-group col-sm-6">
<label htmlFor="firstName">First Name</label>
<input
type="text"
className="form-control"
id="firstName"
name="firstName"
value={inputField.firstName}
onChange={this.onChange.bind(index)}
/>
</div>
<div className="form-group col-sm-4">
<label htmlFor="lastName">Last Name</label>
<input
type="text"
className="form-control"
id="lastName"
name="lastName"
value={inputField.lastName}
onChange={this.onChange.bind(index)}
/>
</div>
<div className="form-group col-sm-2">
<button
className="btn btn-link"
type="button"
onClick={() => this.handleRemoveFields(index)}
>
-
</button>
<button
className="btn btn-link"
type="button"
onClick={() => this.handleAddFields()}
>
+
</button>
</div>
</div>
))}
</div>
<div className="submit-button">
<button
className="btn btn-primary mr-2"
type="submit"
// onSubmit={this.handleSubmit}
>
Save
</button>
</div>
<br />
<pre>{JSON.stringify(this.state.inputFields, null, 2)}</pre>
</form>
</>
);
}
}
export default App;
You approach is not the correct. Use object to contain form values
state = {
inputFields: { firstName: '', lastName: '' }
}
onChange = (e) => {
const { name, value } = e.target;
this.setState(prevState => ({ inputFields: { ...prevState.inputFields, [name]: value } }));
}
// in jsx
<input name="firstName" onChange={this.onChange} />
try this
onChange={(e)=>{this.onChange(e, index)}}
instead of
onChange={this.onChange.bind(index)}
1) Since your inputFields state is an array, you can't just call this.state.inputFields.firstName and even less inputField.firstName.
You have to call this.state.inputsFields[0].firstName.
2) If you want the index AND the event, you have to pass the onChange event like this :
<input
type="text"
className="form-control"
id="lastName"
name="lastName"
onChange={event => this.handleChange(event, index)}
/>
handleChange = (event, index) => {
console.log(event.currentTarget.value, index);
};
// output : {whatever you type} {index of the form}
// exemple : "hello 1"
How to set defaultValue to input component?
<Field name={`${prize}.rank`} defaultValue={index} component={Input} type='text'/>
I tried like above but my fields are empty. I'm trying to create fieldArray (dynamic forms):
{fields.map((prize, index) =>
<div key={index} className="fieldArray-container relative border-bottom" style={{paddingTop: 35}}>
<small className="fieldArray-title marginBottom20">Prize {index + 1}
<button
type="button"
title="Remove prize"
className="btn btn-link absolute-link right"
onClick={() => fields.remove(index)}>Delete</button>
</small>
<div className="row">
<div className="col-xs-12 col-sm-6">
<Field name={`${prize}.rank`} defaultValue={index} component={Input} type='text'/>
<Field name={`${prize}.prizeId`} defaultValue={index} component={Input} type='text'/>
<Field
name={`${prize}.name`}
type="text"
component={Input}
label='Prize Name'/>
</div>
<div className="col-xs-12 col-sm-6">
<Field
name={`${prize}.url`}
type="text"
component={Input}
label="Prize URL"/>
</div>
<div className="col-xs-12">
<Field
name={`${prize}.description`}
type="text"
component={Input}
label="Prize Description" />
</div>
</div>
</div>
)}
On redux forms you can call initialize() with an object of values like so:
class MyForm extends Component {
componentWillMount () {
this.props.initialize({ name: 'your name' });
}
//if your data can be updated
componentWillReceiveProps (nextProps) {
if (/* nextProps changed in a way to reset default values */) {
this.props.destroy();
this.props.initialize({…});
}
}
render () {
return (
<form>
<Field name="name" component="…" />
</form>
);
}
}
export default reduxForm({})(MyForm);
This way you can update the default values over and over again, but if you just need to do it at the first time you can:
export default reduxForm({values: {…}})(MyForm);
This jsfiddle has an example
https://jsfiddle.net/bmv437/75rh036o/
const renderMembers = ({ fields }) => (
<div>
<h2>
Members
</h2>
<button onClick={() => fields.push({})}>
add
</button>
<br />
{fields.map((field, idx) => (
<div className="member" key={idx}>
First Name
<Field name={`${field}.firstName`} component="input" type="text" />
<br />
Last Name
<Field name={`${field}.lastName`} component="input" type="text" />
<br />
<button onClick={() => fields.remove(idx)}>
remove
</button>
<br />
</div>
))}
</div>
);
const Form = () => (
<FieldArray name="members" component={renderMembers} />
);
const MyForm = reduxForm({
form: "foo",
initialValues: {
members: [{
firstName: "myFirstName"
}]
}
})(Form);
this is my implementation using a HoC
import { Component } from 'react'
import {
change,
} from 'redux-form'
class ReduxFormInputContainer extends Component{
componentDidMount(){
const {
initialValue,
meta,
} = this.props
if(initialValue === undefined || meta.initial !== undefined || meta.dirty) return
const {
meta: { form, dispatch },
input: { name },
} = this.props
dispatch(change(form, name, initialValue))
}
render(){
const {
initialValue,
component: Compo,
...fieldProps
} = this.props
return <Compo {...fieldProps} />
}
}
function reduxFormInputContainer(component){
return function(props){
return <ReduxFormInputContainer {...props} component={component} />
}
}
export default reduxFormInputContainer
and then for exemple:
import reduxFormInputContainer from 'app/lib/reduxFormInputContainer'
InputNumericWidget = reduxFormInputContainer(InputNumericWidget)
class InputNumeric extends Component{
render(){
const props = this.props
return (
<Field component={InputNumericWidget} {...props} />
)
}
}
I have a problem with the ref:
<form className="form" onSubmit={(e)=> e.preventDefault() }>
<InputInForm name="number" ref="shareNumder" id="shareNumder" />
<Button className="count" value="count" onClick={this.result} />
</form>
result(e)
{
let sharePric2e = this.refs.sharePrice.value.replace(/ /g, '');
console.log(sharePric2e);
}
and function which gets the ref:
function InputInForm(props) {
return (
<div className="inputs">
<span className="titleInput">{props.name}</span>
<input type="text" id={props.id} ref={props.ref} className="formBlock" placeholder="Введите значение"/>
</div>
);
}
export default InputInForm;
And I got an error "TypeError: this.refs.sharePrice is null".
How I can get value of input using ref ?