I am new to React JS. I am trying to capture the edited value from formcontrol in handle change and assign it to a state object and later retrieve assign it to a variable to pass it as a part of the query string to an API for updating the field, handle change is the function called from form-control to assign the edited value to a state object. I am unable to do so; please provide your inputs. Your help is much appreciated. I would like to follow the same for other fields too.
import React, { PropTypes, Component } from 'react';
import {
Panel,
Button,
PageHeader,
ControlLabel,
FormControl,
Pagination,
Form,
Accordion,
Col,
Radio,
FormGroup
} from 'react-bootstrap';
import StatWidget from '../../src/components/Widget';
import CRUDTable,
{
Fields,
Field,
CreateForm,
UpdateForm,
DeleteForm,
} from 'react-crud-table';
const DescriptionRenderer = ({ field }) => <textarea {...field} />;
const styles = {
container: { margin: 'auto', width: 'fit-content' },
};
class displayDetails extends Component {
constructor (props) {
super(props);
this.state = {
updatecustomer: [],
delcustomer: [],
field1 = '',
};
this.handleUpdate = this.handleUpdate.bind(this);
this.handleDelete = this.handleDelete.bind(this);
this.handleCreate = this.handleCreate.bind(this);
this.handleChange = this.handleChange.bind(this);
};
handleChange (e) {
this.state.field1 = e.target.value; // This isn't happening
}
render() {
firstName=this.props.respData.FIELD1;
lastName=this.props.respData.FIELD2;
return (
<div>
<br></br>
<div className="col-lg-3 col-md-6">
<StatWidget
style="panel-primary"
icon="fa fa-dollar fa-5x"
count={this.props.respData.FIELD1}
headerText="FIELD1"
linkTo=""
/>
</div>
<div className="col-lg-3 col-md-6">
<StatWidget
style="panel-green"
icon="fa fa-phone fa-5x"
count={this.props.respData.FIELD2}
headerText="FIELD2"
linkTo=""
/>
</div>
<div className="col-lg-3 col-md-6">
<StatWidget
style="panel-yellow"
icon="fa fa-home fa-5x"
count={this.props.respData.FIELD3}
headerText="FIELD3"
linkTo=""
/>
</div>
<div className="col-lg-3 col-md-6">
<StatWidget
style="panel-red"
icon="fa fa-shopping-bag fa-5x"
count={this.props.respData.FIELD4}
headerText="FIELD4"
linkTo=""
/>
</div>
<div>
<tr>
<td><h1>{this.props.respData.FIELD1} {this.props.respData.FIELD2}</h1></td>
</tr>
</div>
<div>
<table>
<tr>
<td>
<FormGroup style={spacing}>
<ControlLabel>FIELD 1</ControlLabel>
<FormControl onChange={((e) => this.handleChange(this.props.respData.FIELD1))}
value={this.props.respData.FIELD1}
id="field1" name="field1"
type="text"
placeholder="Enter Text"
/>
</FormGroup>
</td>
</tr>
<br></br>
</table>
</div>
<br></br>
</div>
)
}
}
export default displayDetails;
Modifying the state directly will not work. The only place you should be setting it directly, is to assign the initial state in your constructor. Everywhere else, you need to use this.setState, to notify your component to recheck the state for a possible rerender:
handleChange(e){
this.setState({
field1: e.target.value
});
}
I believe you are in need of the setState() lifecycle method.
handleChange(e){
this.state.field1 = e.target.value; // This isn't happening
this.setState({
field1: e.target.value
}); // this will update state and trigger rerender
}
class displayDetails extends Component {
constructor(props) {
super(props);
this.state = {
state1: [],
state2: [],
state3: '',
state4: '',
state5: '',
state6: '',
state7: '',
state8: '',
state9: '',
state10: '',
};
this.handleState1change = this.handleState1change.bind(this);
this.handleState2change = this.handleState2change.bind(this);
this.handleState3change = this.handleState3change.bind(this);
this.handleState4change = this.handleState4change.bind(this);
field1=this.props.respData.FIELD1;
this.setState({state3:field1});
};
handlestate1change (e) {
console.log('Inside handle state1 Change',e);
this.setState({state3:e.target.value});
console.log('state1 in handlestate1change',this.state.state3);
}
componentWillReceiveProps(){
this.setState({state3:field1});
console.log('newfirstName in Component will mount',this.state.state3);
}
render() {
return(
<td>
<FormGroup style={spacing}>
<ControlLabel>Field1</ControlLabel>
<FormControl onChange={this.handleState1change}
value={this.state.state3}
id="field1" name="field1"
type="text"
placeholder="Enter Text"
/>
</FormGroup>
</td>
);
}
}
}
Related
Warning: A component is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.
import React, { useEffect, useState } from 'react';
import axios from "axios"
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
function CreateExercise() {
const [createExercises, setExercise] = useState({
username: "",
description: "",
duration: 0,
date: new Date(),
users: []
});
useEffect(() => {
axios.get('http://localhost:5000/users/')
.then(response => {
if (response.data.length > 0) {
setExercise({
users: response.data.map(user => user.username),
username: response.data[0].username
})
}
})
}, [])
function handleChange(event) {
const { name, value } = event.target;
setExercise(prevExercise => {
return {
...prevExercise,
[name]: value
};
});
}
function changeDate(date) {
setExercise(prevExercise => {
return {
username: prevExercise.username,
description: prevExercise.description,
duration: prevExercise.duration,
date: date,
users: prevExercise.users
};
});
}
function onSubmit(event) {
event.preventDefault();
console.log(createExercises);
axios.post('http://localhost:5000/exercises/add', createExercises)
.then(res => console.log(res.data));
setExercise({
username: "",
description: "",
duration: 0,
date: new Date(),
users: []
});
window.location = '/';
}
return (
<div>
<h3>Create New Exercise log</h3>
<form >
<div>
<label>Username: </label>
<select
required
className="form-control"
value={createExercises.username}
onChange={handleChange}>
{
createExercises.users.map(function (user, index) {
return <option key={user} value={user}>{user}</option>;
})
}
</select>
</div>
<div className="form-group">
<label>Description: </label>
<input type="text"
name="description"
className="form-control"
onChange={handleChange}
value={createExercises.description}
/>
</div>
<div className="form-group">
<label>Duration (in minutes): </label>
<input type="text"
name="duration"
className="form-control"
onChange={handleChange}
value={createExercises.duration}
/>
</div>
<div className="form-group">
<label>Date: </label>
<DatePicker
selected={createExercises.date}
onChange={changeDate}
/>
</div>
<div className="form-group">
<button type="submit" className="btn btn-primary" onClick={onSubmit} >Create Exercise Log</button>
</div>
</form>
</div>
);
}
export default CreateExercise;
how can i avoid above console error occured?
I think your problem is in your effect, particularly in the way you use setExercise, when you do:
setExercise({
users: response.data.map(user => user.username),
username: response.data[0].username
})
It doesn't "merge" (assign) the new data with previous state, what it does - is just sets the state, meaning your state object after this will be:
{ users:[], username:''}
So you actually lose description and other fields - hence the warning.
What you should do, is this:
setExercise((prevState) => ({
...prevState,
users: response.data.map(user => user.username),
username: response.data[0].username
}))
I'm working in a personal project and I was trying to implement a string interpolation, but for some reason it isn't working and it is throwing an error.
I'm using visual studio code and the errors it's throwing are the following:
Property assignement expected
';' expected (2 times)
Declaration or statement expected
this is the line where I put the specific interpolation:
newsection = {`${newsectionnmb}`:"placeholder"}
this is my complete code:
import React, { Component } from "react";
import { NavLink, match } from "react-router-dom";
import { withRouter } from "react-router-dom";
import axios from "axios";
class AddContent extends Component{
constructor(props) {
super(props)
this.state = {
name: "",
content: "",
courseName:"",
actualContent: [],
section:"NEW",
video: ""
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount() {
axios.get(`http://localhost:5000/course/id/${Number(this.props.match.params.id)}`)
.then( (response)=> {
this.setState({
courseName: response.data.name,
actualContent: response.data.content
});
if(this.props._id != response.data.adminId) {
this.props.history.push("/");
}
})
.catch(function (error) {
console.log(error);
alert("we couldn't fetch the course data, try again later by reloading the page")
})
}
handleChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSubmit= (event)=> {
if (this.state.name !== "" ) {
if (this.state.section === "NEW") {
newsectionnmb = this.state.actualContent.length +1;
newsection = {`${newsectionnmb}`:"placeholder"}
}
event.preventDefault();
axios({
method: 'put',
url: `http://localhost:5000/course/add-content/${Number(this.props.match.params.id)}`,
data: {
content: this.state.content
}
})
}
}
render() {
let sectionlist = this.state.actualContent.length > 0
&& this.state.actualContent.map((item, i) => {
return (
<option key={i} value={item.name}>{item.name}</option>
)
}, this);
return (
<div className="courses">
{this.props.registered === true?
<div>
<form onSubmit={this.handleSubmit} className="Register">
<h1>Add guide</h1>
<h2>{this.state.courseName}</h2>
<p>quotation marks aren't allowed</p>
<div>
<input
name="name"
type="text"
onChange={this.handleChange}
placeholder="name"/>
</div>
<div>
<input
name="video"
type="text"
onChange={this.handleChange}
placeholder="URL for video"/>
</div>
<div>
<textarea
name="content"
type="text"
onChange={this.handleChange}
placeholder="content"/>
</div>
<label>select section:</label>
<select name="section" onChange={this.handleChange} className="select">
<option value="NEW">New Section</option>
{sectionlist}
</select>
<button type="submit" className="coursesub">Submit</button>
<NavLink exact to="/courses">Go back to course</NavLink>
</form>
</div>
:
<div>
<h1>Welcome to SSG courses app, to start using please login.</h1>
<NavLink exact to="/login">Login</NavLink>
</div>
}
</div>
)
}
}
export default withRouter(AddContent);
If you want to make newsection an object, it should be done like this
newsection = {newsectionnmb:"placeholder"}
If you are trying to make it a string, this should work for you
newsection = `${newsectionnmb}:"placeholder"`
I am looking to create a form with a datepicker in my React component with materialize-css. I don't have many fields this form is capturing and the structure is fairly simple. The form returned looks like this:
<form onSubmit={this.handleSubmit.bind(this)}>
<div className="container">
<div className="card grey lighten-3">
<div className="card-content black-text">
<span className="card-title">
<input placeholder="Event Name"
name="name" value={this.state.name}
onChange={this.handleStateChange.bind(this)}/>
</span>
<input name="description" placeholder="Description"
value={this.state.description}
onChange={this.handleStateChange.bind(this)}/>
<input name="image" placeholder="Image URL"
value={this.state.image}
onChange={this.handleStateChange.bind(this)}/>
<input placeholder="Start Date"
className="datepicker" name="startDate" value={this.state.startDate}
onSelect={this.handleStateChange.bind(this)}/>
</div>
<div class="card-action">
<div className="row">
<span>
<div className="col s3">
<input className="btn light-blue accent-1" type="submit" value="Submit"/>
</div>
<div className="col s3">
<a className="btn grey" onClick={this.handleExpand.bind(this)}>Cancel</a>
</div>
</span>
</div>
</div>
</div>
</div>
</form>
The state change is handled with
handleStateChange(item) {
this.setState({[item.target.name]: item.target.value});
}
and I have called the AutoInit to initialize my datepicker
M.AutoInit();
I've tried using onChange instead of onSelect to manage the datepicker state change, but it doesn't seem to capture that event. With onSelect used, the date sometimes gets capture if I pick a date then re-open the datepicker.
I have also tried using some of the alternate initialization methods for the datepicker to no avail.
How do I correctly capture the input change with my given setup?
Hi hopefully this will help somebody -
What happens with the <DatePicker /> component is that the default onChange method returns the date (2019-08-01) and not the the element's event handler object. In order to counter this we need to create an object inside the onChange method that mimics the eventhandler's target.id and target.value
Other components like the <input /> works as per normal. Check it out:
This is what the component should look like:
<DatePicker
label="myDate"
value={state.myDate}
id="myDate"
onChange={(newDate) => {
handleChange({
target: {
id: "myDate",
value: newDate
}
})
}} />
Here is the full code:
import React, { useState, useEffect } from "react";
import "materialize-css/dist/css/materialize.min.css";
import "materialize-css/dist/js/materialize.min.js";
import { DatePicker } from "react-materialize";
const PickDate = (props) => {
const [state, setState] = useState({myName: "Mags", myDate: "2019-08-01"});
const handleChange = (e) => {
const key = e.target.id;
const val = e.target.value;
const newState = {...state};
newState[key] = val;
setState(newState);
}
return (
<React.Fragment>
<input type="text" value={state.myName} id="myName" onChange={handleChange} />
<DatePicker
label="myDate"
value={state.myDate}
id="myDate"
onChange={(newDate) => {
handleChange({
target: {
id: "myDate",
value: newDate
}
})
}} />
</React.Fragment>
);
}
export default PickDate;
PS. this uses React Hooks - but it will work on normal classes too.
After studing all the saturday about the lifecycle of React. I got this solution for this:
The use of the component:
<DatePicker label="Fecha" value={this.state.formSchedule.start}
onChange={(date) => {
this.state.formSchedule.start = date;
this.setState({ formSchedule: this.state.formSchedule });
}}/>
The Class DatePicker.tsx:
import * as React from 'react';
import Materialize from 'materialize-css';
import moment from 'moment'
import 'moment/locale/es'
import { any } from 'prop-types';
interface IState {
value: any;
}
interface IProps {
label: any;
format: any;
onChange: any;
formatMoment: any;
}
export default class DatePicker extends React.Component<IProps, IState> {
static defaultProps = {
label: "Fecha",
value: new Date(),
format: 'ddd d, mmm',
formatMoment: 'ddd D, MMM'
}
constructor(props: any) {
super(props);
this.componentWillReceiveProps(props);
}
componentWillReceiveProps(props) {
this.state = {
value: props.value
};
}
render() {
return <div className="input-field col s6">
<i className="material-icons prefix">date_range</i>
<input id="date" type="text" className="datepicker queso"
value={moment(this.state.value).locale('es').format(this.props.formatMoment)}
/>
<label className="active" htmlFor="date">{this.props.label}</label>
</div>;
}
componentDidMount() {
var context = this;
var elems = document.querySelectorAll('.queso');
Materialize.Datepicker.init(elems, {
defaultDate: new Date(),
format: this.props.format,
container: 'body',
onSelect: function (date) {
context.setState({ value: context.state.value });
context.props.onChange(date);
},
autoClose: true
} as Partial<any>);
}
}
Thanks Lucas, your answer also helped me.
Here is my solution -without redux or props, just the class component with its own state
import React, { Component } from "react";
import "./calendar.css";
import Materialize from "materialize-css";
import moment from "moment";
class Calendar extends Component {
componentDidMount() {
var context = this;
var elems = document.querySelectorAll(".dateset");
Materialize.Datepicker.init(elems, {
defaultDate: new Date(),
format: this.state.format,
container: "body",
onSelect: function(date) {
context.setState({ value: context.state.value });
console.log(date); // Selected date is logged
},
autoClose: true
});
}
state = {
value: new Date(),
format: "ddd d, mmm",
formatMoment: "ddd D, MMM"
};
render() {
return (
<div className="input-field col s6">
<i className="material-icons prefix">date_range</i>
<input
id="date"
type="text"
className="datepicker dateset"
defaultValue={moment(this.state.value).format(
this.state.formatMoment
)}
/>
</div>
);
}
}
export default Calendar;
None of the already added answers helped me, so I decided to do it in my way.
I did not install Materialize and jQuery into my modules, just added them in index.html
When you click on input field, then datepicker modal window opens and there two buttons CANCEL and OK. I find that OK button by jQuery and add click function, which takes value from input field and updates the state;
componentDidMount(){
window.$(".datepicker-done").click(() => {
var datepickerValue = window.$("#date-input").val(); // date-input it's 'id' on datepicker input
this.setState({ approxLastDay: datepickerValue });
});
}
NOTE: datepickerValue will be in string format (e.g. "Aug 6, 2019")
I having the same problem, here is my solution.
import React, { Component } from 'react'
import M from 'materialize-css';
class CreateReport extends Component {
constructor(props) {
super(props);
this.state = {
startDate: '',
endDate: ''
};
// refs for startDate, endDate
this.startDate = React.createRef();
this.endDate = React.createRef();
}
componentDidMount() {
var context = this;
document.addEventListener('DOMContentLoaded', function () {
var start = document.querySelectorAll('.datepicker');
M.Datepicker.init(start, {
format: "mm/dd/yyyy",
autoClose: true,
onClose: context.handleDate
});
});
}
handleDate = () => {
this.setState({
startDate: this.startDate.current.value,
endDate: this.endDate.current.value,
})
// console.log(this.state.startDate)
// console.log(this.state.endDate)
}
handleChange = (e) => {
this.setState({
[e.target.id]: e.target.value
})
}
handleSumbit = (e) => {
e.preventDefault();
console.log(this.state)
}
render() {
return (
<div>
<div className="container">
<form onSubmit={this.handleSumbit} className="white col s12 m6">
<div className="row">
<div className="input-field col s3 offset-s2">
<label htmlFor="date">Start Date</label>
<input
type="text"
className="datepicker"
id="startDate"
onChange={this.handleChange}
value={this.state.startDate}
ref={this.startDate}
/>
</div>
<div className="input-field col s3 offset-s2">
<label htmlFor="date">End Date</label>
<input
type="text"
className="datepicker"
id="endDate"
onChange={this.handleChange}
value={this.state.endDate}
ref={this.endDate} />
</div>
</div>
<div className="col s8 offset-s2 center-align">
<button className="btn pink lighten-1 z-depth-0 ">Sign Up</button>
</div>
</form>
</div>
</div >
)
}
}
export default CreateReport
I made a less elegant solution, but it's also quite a few lines of code. And it seems to be working (after hours of debugging!).
I made a css-class called trouble and applied it to all the fields dealing with DatePicker and TimePicker. In the intialization I created eventlisteners to check for changes. When a change had been detected it calles the _valueTracker, and causes it to send an update event that redux notices.
One very strange thing is that if I pass in the exactly the same value as on e.target.value, it does nothing. It needs to be a string of something random such as "UPDATE!" in this case. I use this code along with the rest of the materialize initialization.
const troubles = document.querySelectorAll(".trouble");
troubles.forEach((item) => {
item.addEventListener("change", (e) => {
e.target._valueTracker.setValue("UPDATE!");
});
});
I am trying to create a button that will add a new input element to a page and then as I type display its changes.
However when I type into the input fields in <Input />, for some reason the state isn't changing. The input fields stay blank.
Out of curiosity, I removed the button that adds the <Input /> component and ran it with one <Input /> field on the page. When I type into one of the input fields, I can see my text.
It seems that when I add a new component to the page and try to change the state, something is off.
What am I doing wrong?
function Input(props) {
console.log(props)
return (
<div>
<div><input name="pitchName" value={props.currentValue.pitchName} placeholder="Pitch Name" onChange = {props.updateNewPitch}/></div>
<div><input name="shortCut" value={props.currentValue.shortcut} placeholder="Short cut" onChange = {props.updateNewPitch} /></div>
<div><input name="subject" value={props.currentValue.subject} placeholder="Subject" onChange = {props.updateNewPitch} /></div>
<div><textarea name="pitch" value={props.currentValue.pitch} onChange = {props.updateNewPitch}/></div>
<button type="submit" onClick={props.savePitch} >Add Pitch</button>
</div>
)
}
// function SavedPitches(props)
class Form extends React.Component{
constructor(props){
super(props);
this.state = {
inputList: [],
addNewPitch: {
pitchName: '',
shortCut: '',
subject: '',
pitch: ''
},
savedPitches: []
};
this.onAddBtnClick = this.onAddBtnClick.bind(this)
this.savePitch = this.savePitch.bind(this)
this.updateNewPitch = this.updateNewPitch.bind(this)
}
updateNewPitch(e){
this.setState({addNewPitch: {...this.state.addNewPitch, [e.target.name]: e.target.value}})
}
onAddBtnClick(event){
const inputList = this.state.inputList;
this.setState({
inputList: inputList.concat(
<Input savePitch={this.savePitch}
currentValue = {this.state.addNewPitch}
updateNewPitch={this.updateNewPitch}
/>
)
})
}
render() {
return(
<div>
<button onClick={this.onAddBtnClick}>Add input</button>
<div></div>
{
this.state.inputList
}
</div>
)
}
}
ReactDOM.render(<Form />,document.getElementById('root'));
Reason is because you are storing the Input (UI element) in state variable, and that variable is not getting update only values are getting updated in a separate state variable addNewPitch.
Suggestion:
1- Storing UI elements in state variable is not a good idea, always store value in state and all the ui logic should be inside render function.
2- Use a state variable and toggle the Input (UI element) on the basis of that.
Check working solution (check the values on addNewPitch inside render it will get updated properly):
function Input(props) {
return (
<div>
<div><input name="pitchName" value={props.currentValue.pitchName} placeholder="Pitch Name" onChange = {props.updateNewPitch}/></div>
<div><input name="shortCut" value={props.currentValue.shortcut} placeholder="Short cut" onChange = {props.updateNewPitch} /></div>
<div><input name="subject" value={props.currentValue.subject} placeholder="Subject" onChange = {props.updateNewPitch} /></div>
<div><textarea name="pitch" value={props.currentValue.pitch} onChange = {props.updateNewPitch}/></div>
<button type="submit" onClick={props.savePitch} >Add Pitch</button>
</div>
)
}
class Form extends React.Component{
constructor(props){
super(props);
this.state = {
inputList: [],
addNewPitch: {
pitchName: '',
shortCut: '',
subject: '',
pitch: ''
},
savedPitches: []
};
this.onAddBtnClick = this.onAddBtnClick.bind(this)
this.savePitch = this.savePitch.bind(this)
this.updateNewPitch = this.updateNewPitch.bind(this)
}
savePitch() {
}
updateNewPitch(e){
this.setState({addNewPitch: {...this.state.addNewPitch, [e.target.name]: e.target.value}})
}
onAddBtnClick(event){
const inputList = this.state.inputList;
this.setState({
show: true,
addNewPitch: {
pitchName: '',
shortCut: '',
subject: '',
pitch: ''
}
})
}
render() {
console.log('addNewPitch', this.state.addNewPitch);
return(
<div>
<button onClick={this.onAddBtnClick}>Add input</button>
<div></div>
{
this.state.show && <Input
savePitch={this.savePitch}
currentValue = {this.state.addNewPitch}
updateNewPitch={this.updateNewPitch}
/>
}
</div>
)
}
}
ReactDOM.render(<Form />,document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='root'/>
I am working with redux-form and it seems confusing me to load initial data for edit form but the data is not being validated on submit. I have managed to pass and load data into the fields but that seems not loading into the form props etc. Please see the following piece of code and let me know if need something more.
Form_Bayan.js
import React, {Component, PropTypes} from "react";
import {browserHistory} from "react-router";
import {reduxForm, Field} from "redux-form";
import {MyCustomInput, MySimpleInput, MyCustomSelect} from "./__form_field_components";
import {connect} from "react-redux";
import {bindActionCreators} from "redux";
import {
ADMIN_FETCH_AUTOSUGGESTS_Lbl,
adminFetchAutoSuggestCats_act,
ADMIN_GETCATID_BYNAME_Lbl,
adminGetCatIdByName_act,
ADMIN_ADDNEWBAYAAN_Lbl,
adminAddNewBayaan_act,
adminFetchArticlesByCat_act,
adminUpdateBayaan_act
} from "../../actions/adminActionCreators";
import _ from "lodash";
class NewBayanForm extends Component {
constructor(props) {
super(props);
this.state = {
submitButtonMeta: {
btnTitle: "Save",
btnClass: "btn btn-default",
btnIcon: null,
disabled: false
},
globalMessage: { // set when an action is performed by ActionCreation+Reducer and a message is returned
message: "",
className: ""
},
tempData: {
the_bayaansMainCat_id: this.props.associatedMainCatId, // being passed from parent component to avoide redundent declaration
the_autoSuggestCatList: [],
slug: "",
the_catId: null
}
};
}
resetMessageState() {
var noMsg = {message: "", className: ""};
this.setState({globalMessage: noMsg});
}
componentDidMount() {
this.props.adminFetchAutoSuggestCats_act(this.state.tempData.the_bayaansMainCat_id);
}
doSubmit(props) {
var newBayanObj = {
item_title: props.titleTxt,
item_slug: this.state.tempData.slug,
content: props.videoIdTxt,
picture: "",
attachment: "",
media_path: "https://www.youtube.com/watch?v=" + props.videoIdTxt,
reference: "",
tag_keywords: props.keywordsTxt,
author_name: props.authorTxt,
cat_id: this.state.tempData.the_catId
};
this.props.adminUpdateBayaan_act(newBayaanObj)
.then(() => {
this.props.adminFetchArticlesByCat_act(this.props.associatedMainCatId)
.then(() => {
this.props.toggleViewFunction(); // comming from Parent Class (bayaansPage)
});
});
}
fetchCategoryId(value) {
// make API call to fetch / generate category ID for this post
this.props.adminGetCatIdByName_act(value, this.state.tempData.the_bayaansMainCat_id); // '1': refers to look up under 'Bayaans' parent category for the specified category name
}
// will always receive and triggers when there are 'new props' and not old/same props
render() { // rendering Edit form
const {handleSubmit} = this.props;
console.log('<NewBayanForm> (render_editForm) this.props:', this.props);
return (
<div className="adminForm">
<form onSubmit={handleSubmit(this.doSubmit.bind(this))}>
<div className="col-sm-6">
<div className="row">
<div className="col-sm-5"><label>Title:</label></div>
<div className="col-sm-7"><Field name="titleTxt" component={MySimpleInput}
defaultValue={this.props.name} type="text"
placeholder="Enter Title"/></div>
</div>
<div className="row">
<div className="col-sm-5"><label>Slug:</label></div>
<div className="col-sm-7">{this.state.tempData.slug || this.props.slug} <input
type="hidden" name="slugTxt" value={this.state.tempData.slug}/></div>
</div>
<div className="row">
<div className="col-sm-5"><label>Select Category:</label></div>
<div className="col-sm-7"><Field name="catTxt" component={MyCustomSelect}
defaultValue={this.props.category_name} type="text"
placeholder="Select or Type a New"
selectableOptionsList={this.state.tempData.the_autoSuggestCatList}
onSelectionDone={ this.fetchCategoryId.bind(this) }/>
<input type="hidden" name="catIdTxt"
value={this.state.tempData.the_catId || this.props.category_id}/>
</div>
</div>
</div>
<div className="col-sm-6">
<div className="row">
<div className="col-sm-5"><label>Youtube Video ID:</label></div>
<div className="col-sm-7"><Field name="videoIdTxt" component={MySimpleInput}
defaultValue={this.props.content} type="text"
placeholder="TsQs9aDKwrw"/></div>
<div className="col-sm-12 hint"><b>Hint: </b> https://www.youtube.com/watch?v=<span
className="highlight">TsQs9aDKwrw</span></div>
</div>
<div className="row">
<div className="col-sm-5"><label>Author/Speaker:</label></div>
<div className="col-sm-7"><Field name="authorTxt" component={MySimpleInput}
defaultValue={this.props.author} type="text"/></div>
</div>
<div className="row">
<div className="col-sm-5"><label>Tags/Keywords:</label></div>
<div className="col-sm-7"><Field name="keywordsTxt" component={MySimpleInput}
defaultValue={this.props.tag_keywords} type="text"/>
</div>
</div>
</div>
<div className="row">
<div className={this.state.globalMessage.className}>{this.state.globalMessage.message}</div>
</div>
<div className="buttonControls">
<a className="cancelBtn" onClick={this.props.toggleViewFunction}>Cancel</a>
<button className={this.state.submitButtonMeta.btnClass}
disabled={this.state.submitButtonMeta.disabled}>
{this.state.submitButtonMeta.btnTitle}</button>
</div>
</form>
</div>
);
}
}
function validate(values) { // Validate function being called on Blur
const errors = {};
if (!values.titleTxt)
errors.titleTxt = "Enter Title";
if (!values.catTxt)
errors.catTxt = "Select/Enter a Category";
if (!values.videoIdTxt)
errors.videoIdTxt = "Enter youtube video ID (follow the provided hint)";
if (!values.keywordsTxt)
errors.keywordsTxt = "Enter keywords (will help in search)";
return errors;
}
// ReduxForm decorator
const newBayanFormAdmin_reduxformObj = reduxForm({
form: "newBayanFormAdmin", // any unique name of our form
validate // totally equivelent to--> validate: validate
});
function mapStateToProps({siteEssentials}, ownProps) {
// 1st param is related to our Redux State, 2nd param relates to our own component props
var initialValues = {
titleTxt: ownProps.name,
slugTxt: ownProps.slug,
catTxt: ownProps.category_name,
catIdTxt: ownProps.category_id,
videoIdTxt: ownProps.content,
authorTxt: ownProps.author,
keywordsTxt: ownProps.tag_keywords
};
return ({siteEssentials}, initialValues);
};
function mapDispatchToProps(dispatch) {
return bindActionCreators({
adminFetchAutoSuggestCats_act,
adminGetCatIdByName_act,
adminAddNewBayaan_act,
adminFetchArticlesByCat_act
}, dispatch);
};
NewBayanForm = connect(mapStateToProps, mapDispatchToProps) (newBayanFormAdmin_reduxformObj(NewBayanForm));
export default NewBayanForm;
try initialValues for more details
inside reduxform :
export default NewBayanForm = reduxForm({ form: 'NewBayanForm', initialValues: {
name: "abc",
email: "abc#gmail.com",
phoneNo: "1234567890"
} })(NewBayanForm)
or
<NewBayanForm initialValues={yourObject} />
I found this tutorial which is quite simple and helpful.
https://www.davidmeents.com/?p=38