How can I get the value of datapicker in react toobox?
I am using custom components.
I am using 2 components first one is called InputDateCustom.js with the code below:
import DatePicker from 'react-toolbox/lib/date_picker/DatePicker';
import React, { Component } from 'react';
const datetime = new Date(2015, 10, 16);
datetime.setHours(17);
datetime.setMinutes(28);
export default class InputDateCustomizado extends Component{
state = {date2: datetime};
handleChange = (item, value) => {
console.log(item+" - "+value)
this.setState({...this.state, [item]: value});
};
render() {
return (
<div>
<DatePicker
label={this.props.label}
locale={localeExample}
name={this.props.name}
required={this.props.required}
onChange={this.handleChange.bind(this, 'date1')}
value={this.state.date1}
/>
</div>
);
}
}
Another component is called Cadastro.js that contains the following logic:
constructor(props) {
super(props);
this.state = {msg: '', fim_vigencia:'', nome:''}
this.setNome = this.setNome.bind(this)
this.setFimVigencia = this.setFimVigencia.bind(this)
}
setFimVigencia(evento){
console.log("date")
this.setState({fim_vigencia:evento.target.value});
}
InputDateCustomizado
id="fim_vigencia"
label="Fim"
name="fim_vigencia"
value = {this.state.fim_vigencia}
onSubmit = {this.setFimVigencia}
/>
Get the value in an onChange event or using the value prop. Doc examples: http://react-toolbox.com/#/components/date_picker
<DatePicker label='Birthdate' onChange={this.handleChange.bind(this, 'date1')} value={this.state.date1} />
You can get access to the value in the handleChange event allowing you to update your state with the currently selected date.
EDIT: Ah okay I think I understand what you are asking now. You have wrapped DatePicker with your own component and now you want to get the DatePicker value through the Cadastro.js component.
You need to create a method in the Cadastro.js that accepts state changes from the InputDateCustomizado component and then pass that function as a prop to the InputDateCustomizado component. In the InputDateCustomizado when the state changes, call the passed in function and it should update the state in the parent component. Then you will always have the datepicker value in the parent component.
It looks like you are almost there. You need to add an updateState function to the Cadastro.js component. In the InputDateCustomizado component handleChange event, you need to call this.props.updateState and pass in the new value.
In Cadastro.js
updateState = (data) => {
this.setState({
date: data.data //set your state here to the date
})
}
In InputDateCustomizado
handleChange = (item, value) => {
console.log(item+" - "+value)
this.setState({...this.state, [item]: value});
this.props.updateState(this.state);
};
Related
I made a custom component called TagsInput, and added it to a form. My problem is, when the form is submitted, the value for field tags is always undefined, because the Form.Item cannot retrieve the value from the TagsInput child. This is usually not a problem when children of Form.Item are antd components.
export default function NewProjectForm(props) {
return (
<Form layout="vertical" onFinish={props.onSubmit} id="newProjectForm">
<Form.Item label="Tags" name="tags">
<TagsInput />
</Form.Item>
</Form>
);
}
TagsInput is a class component that has its value within its state:
class TagsInput extends React.Component{
constructor(props){
super(props);
this.state = {
value: []
}
}
render(){
return(<div></div>)
}
}
I dont want to elevate the value field from TagsInput state to NewProjectForm because it is not a class component... I would be doing it just for the sake of solving this issue. I am asking this question because I think there is a cleaner way of solving this.
How can I make NewProjectForm retrieve the value of TagsInput from within its state?
Is there any function I can pass to TagsInput as a property, so that the form asks the component for a value when it is submitted?
In order to achive what you want, you need to handle the state of the form (and its components) at the parent component (NewProjectForm).
If you are willing to keep that component a function component, you can use React Hooks and define a state with useState like this:
const [tagValue, setTagValue] = useState([]);
While tagValue is the value you will get from the child TagsInput, and the setTagValue is the function that can set that value. You need to pass setTagValue as a function prop to TagsInput and use it on change. It will look something like this:
export default function NewProjectForm(props) {
const [tagValue, setTagValue] = useState([]);
return (
<Form layout="vertical" onFinish={props.onSubmit} id="newProjectForm">
<Form.Item label="Tags" name="tags">
<TagsInput setTagValue={(val)=>setTagValue(val)} />
</Form.Item>
</Form>
);
}
class TagsInput extends React.Component{
constructor(props){
super(props);
this.state = {
value: []
}
}
.........
.........
onChangeInput(val){
this.props.setTagValue(val);
}
.........
.........
render(){
return(<div></div>)
}
}
EDIT
After the clarification in the comments, you actually need to follow the steps of using Customized Form Controls, As described here.
You need to pass an object with value and onChange that changes the value. Then, the Form component should manage to get that value automatically.
So I guess it should look something like that:
const TagsInput= ({ value = {}, onChange }) => {
const triggerChange = newValue => {
if (onChange) {
onChange(newValue);
}
};
return(<div></div>)
};
I'm working on a form with Reactjs that gets some defaultValues from the parent component.
The problem is, the parent component set states of the values with a axios post and pass those values to the child as props. I can print those values on the child component with console.log but if I try to put those values on defaultValues on the TextFields I got a empty form, none of the values is rendered on the form.
Parent component:
export default class Parent extends Component {
constructor(props){
super(props);
this.state={
somevalue: '',
}
}
componentDidMount(){
this.getData();
}
getData = async () => {
await api.post('/getValue')
.then((res) => {
this.setState({
someValue: res.data;
})
}).catch((err) => {
console.log("Error: ", err);
})
}
render(){
return(
<Child value={this.state.someValue}/>
)}
}
Child component
export default function Child(props) {
console.log(props.value); // THIS LOG PRINT THE VALUE PROPERLY
return(
<TextField defaultValue={props.value}/>
)
}
This is basically my code structure, but it's not working. TextField still empty after this.
The property defaultValue is only used on the initial render. If you'll inspect your code you'll see that before the console.log outputs the value it will first output undefined. You can either change it to a controlled component by changing defaultValue to value. This way the value will display, but you'll need to add an onChange handler for the changes to the value.
function Child(props) {
// Using the value prop your value will display, but you will also have to pass an onChange handler to update the state in the parent
return <TextField value={props.value} />;
}
Or you can wait until the value is available before rendering your component
const { someValue } = this.state;
if (!someValue) {
return "loading the data";
}
return <Child value={someValue} />;
It depends on the exact situation what solution will be better. But I think it's likely you'll want to update the value in the input and do something with it, so I would go with the first situation.
I have a component called Test that receives 2 props: CurrentPage and OnPageRequest: (currentPage: number) => void
When the parent component uses Test, it sets the Current page number in its state. As you update, the input field below, that value gets fed back up to the parent component via the OnPageRequest as:
OnPageRequest(e.target.value);
wherein return, the parent component updates its current page number in the state.
Test component:
const handlePageNumberBlur = (e) => {
OnPageRequest(e.target.value);
}
render() {
return (
<input
title="Current Page"
onBlur={handlePageNumberBlur}
aria-label="Current Page"
min="1"
max={TotalPages}
placeholder="1"
type="number"
value={this.props.CurrentPage} />
)
}
I'm trying to write Test in such a way so that it only fires back the newly inputted value only when the onBlur event is triggered. But I've learned that with the above code, it never updates the value. It only does it if I have an onChange event where I do: OnPageRequest(e.target.value);
How can I get it to change only when onBlur fires?
SAMPLE: https://codesandbox.io/s/kumuc
Try using defaultValue instead of value. The defaultValue prop only sets the value to the input on initial render and you won´t need to keep it updated if the value of the prop changes.
<input
{ ... }
defaultValue={this.prop.CurrentPage}
/>
But this can also be an issue if you set CurrentPage after the input has rendered, which depends on where you get your initial value for the prop.
If you need to keep the input updated after the first render, you can update its value using Refs and the componentDidUpdate lifecycle method.
class TestComponent extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
componentDidUpdate(prevProps) {
if (this.inputRef.current.value != this.props.CurrentPage) {
this.inputRef.current.value = this.props.CurrentPage;
}
}
/* ... */
render() {
return <input
{ ... }
defaultValue={this.props.CurrentPage}
ref={this.inputRef}
/>
}
}
I have this container where and is not placed in the same level. How can I get the state of the Form when I click on the button (which is placed on the parent) ?
I've created a demo to address my issue.
https://codesandbox.io/s/kmqw47p8x7
class App extends React.Component {
constructor(props) {
super(props);
}
save = () => {
alert("how to get state of Form?");
//fire api call
};
render() {
return (
<div>
<Form />
<button onClick={this.save}>save</button>
</div>
);
}
}
One thing I don't want to do is sync the state for onChange event, because within Form there might be another Form.
To access a child instance from parent, your need to know about ref:
First, add formRef at top your App class:
formRef = React.createRef();
Then in App render, pass ref prop to your Form tag:
<Form ref={this.formRef} />
Finaly, get state from child form:
save = () => {
alert("how to get state of Form?");
const form = this.formRef.current;
console.log(form.state)
};
Checkout demo here
ideally, your form submit action belongs to the Form component
You can put button inside your From component and pass a submit callback to the form.
class App extends React.Component {
constructor(props) {
super(props);
}
save = (data) => {
// data is passed by Form component
alert("how to get state of Form?");
//fire api call
};
render() {
return (
<div>
<Form onFormSubmit={this.save} />
</div>
);
}
}
you can write the code like this
https://codesandbox.io/s/23o469kyx0
As it was mentioned, a ref can be used to get stateful component instance and access the state, but this breaks encapsulation:
<Form ref={this.formRef}/>
A more preferable way is to refactor Form to handle this case, i.e. accept onChange callback prop that would be triggered on form state changes:
<Form onChange={this.onFormChange}/>
One thing I don't want to do is sync the state for onChange event, because within Form there might be another Form.
Forms will need to handle this any way; it would be impossible to reach nested form with a ref from a grandparent. This could be the case for lifting the state up.
E.g. in parent component:
state = {
formState: {}
};
onFormChange = (formState) => {
this.setState(state => ({
formState: { ...state.formState, ...formState }
}));
}
render() {
return (
<Form state={this.state.formState} onChange={this.onFormChange} />
);
}
In form component:
handleChange = e =>
this.props.onChange({
[e.target.name]: e.target.value
});
render() {
return (
<input
onChange={this.handleChange}
name="firstName"
value={this.props.state.firstName}
/>
);
}
Here is a demo.
I have a stateless React function to render a react-select Select to a form. Everything else works nicely with redux-form except when redux-form is reset. I need to reset the form manually after successful post.
onChange and onBlur change the redux-form value correctly when Select has a value change. When I reset the redux-form, the redux-form value is cleared but the Select will have the old value.
function SelectInput(props) {
const { input, options, label } = props;
const { onChange, onBlur } = input;
const handleChange = ({ value }) => {
onChange(value);
};
const handleBlur = ({ value }) => {
onBlur(value);
};
return (
<FormField {...props}>
<Select placeholder={label} options={options} onChange={handleChange} onBlur={handleBlur} />
</FormField>
);
}
I converted the SelectInput to React.PureComponent, and added the value as a state inside the component and looked for when the Component received new props:
constructor(props) {
super(props);
this.state = {value: ''}
}
componentWillReceiveProps(nextProps){
this.setState({value: nextprops.input.value})
}
<Select value={this.state.value} placeholder={label} options={options} onChange={handleChange} onBlur={handleBlur} />
With this Select was not able to show the value at all.
The problem is that how I can update the Select to show empty value when redux-form that this field is part of is reset? Redux-form resets the value corretly inside the redux state and if I try to submit the form, validation notices that that Select has empty value. The Select will however display the old value so that user thinks that there is a value selected.
Reset is done by dispatching reset in the actual redux-form component. Redux devtools show that fields are reset and the redux state is cleared from all the value, Select component just won't update the DISPLAYED value to empty.
const afterSubmit = (result, dispatch) =>
dispatch(reset('datainputform'));
export default reduxForm({
form: 'datainputform',
onSubmitSuccess: afterSubmit,
})(DataInputForm);
Versions I use:
react-select#v2.0.0-beta.6
redux-form#7.3.0
You can also set a key at the form level itself. The key will take a unique value that you can store in the component state. This unique value will be updated every time reset is hit.
state = {
unique_key: ''
}
// this is the onClick handler for reset button on the form
onResetForm = () => {
reset_val = Date.now();
this.props.reset();
this.setState({unique_key: reset_val});
}
<Form actions={action_func}, key={this.state.unique_key}/>
Now whenever reset is clicked, the handler will update the unique_key. This will result in re-rendering the Form with the default values. The handler also calls the form reset function to clear the redux.
Got it working. Problem was handling the Select null value. Changed stateless function to PureComponent, added the value to state.
constructor(props) {
super(props);
this.state = { value: '' };
}
Redux-form changes the react-select value by sending new props. So added
componentWillReceiveProps(nextProps) {
if (nextProps.input.value === '') {
this.setState({ value: '' });
}
}
Added setState to handleChange:
handleChange = (data) => {
const value = data === null ? '' : data;
this.setState({ value });
this.props.input.onChange(data.value);
};
And then added the value prop.
<Select value={this.state.value}...