Adding onChange logic to third-party react-day-picker element - javascript

I'm trying to integrate react-day-picker's DayPicker with react-final-form.
React Final Form requires the use of a Field for each form field, which means creating an adapter component whenever you want to a third-party form element to be usable within the form. The adapter component has to accept an input object containing value and onChange. The advice is just to provide a new onChange.
This approach, which works for many other components, doesn't work for DayPicker. It seems like the issue is that DayPicker doesn't actually have an onChange method, so it's up to us to manage what happens when the calendar changes and then store the dates in value property that react-final-form expects.
I've created a codepen here: https://codesandbox.io/s/github/pcraig3/date-picker-sandbox
I have a handleDayClick method in Calendar.js which runs when days are clicked, but onChange isn't being triggered for the calendar consistently.
selectedDays is being updated immediately within the Calendar itself, but the Form is not getting the correct dates until the calendar is unfocused
The form's validate method is only being called once (the first time selecting a day), whereas it is called each time the native text input value is updated.
I would like the form values to be synced up with the calendar's external state and for the validate method to be triggered each time a day is clicked/unclicked. Is this possible to achieve or am I doing completely the wrong thing?

It's probably easier to use the <DayPickerInput> component, instead. That component uses a standard HTML input, which supports onChange. I did it like this:
<Field name={id}>
{({ input, meta }) => (
<React.Fragment>
<label htmlFor={id}>Date: </label>
<DayPickerInput
{...input}
onDayChange={day => input.onChange(day)}
inputProps={{ id: id }}
/>
{meta.error && meta.touched && <div className="error">{meta.error}</div>}
</React.Fragment>
)}
</Field>

According to the documentation, you can add the logic to the "inputProps" prop, since this takes in props to the input component, you can also add css to it as well.
inputProps Object
: Additional props to add to the input component.
Your code will look like this:
const dateChanged = day => (console.log(day)); //function to call when date changes
inputProps={{
style: styles.dayPickerInput,
onChange: event => dateChanged(event.target.value),
}}
If you use onDayChange alone, it'll fire after the user "clicks" to select a day, not when the user actually types a date inside the input field, using this extra onchange listener will be a safeguard for you, if the input field is enabled for users to type in the date, which they might.

Related

update input field value in react JS state

this is my first question here,pardon me for any mistake. So ,I have a few inputs and for displaying the values of them I used some elements like h1 and div's which are in a seperate component. I want my elements to have some default value, so for that I kept them in state and then I call an onChange function on inputs which will update my elements state. I tried doing it with event.target like nameElement:event.target.value ,it would have worked if i had one input but because I have multiple inputs ,when I change an input field it gets overwritten by the one I change next. So how can I update only the input field I change. Like if I write something in name input field only the element of CV which is holding the name field should change . Here's my code sandbox link https://codesandbox.io/s/cool-glitter-9w2mh?file=/src/App.js
I am not sure, I got the issue right. But I got into the sandbox and below are my observations.
I would advise using Formik if you are dealing with the user-input form. Link - https://formik.org/docs/tutorial
Since you have created a single state that contains default value as well as user input value, any changes made by the user is not saved after clicking on "viewCV" link that re-renders entire component.
Changes Required
Have two states : initialData and userDetails.
Modify handleChange
handleChange = (input, e) => {
this.setState((prevState) => {
return {
...prevState,
[input]: e.target.value
};
});
};
In components such as workExp, education make sure you link handleChange as an arrow function for the "onChange" event.
<input onChange={(e) => handleChange("job", e)}>Email
Modify submit button to render the Resume template with user inputted values.
Modify viewCV link which is causing entire parent component re-rendering.

Is this a controlled or uncontrolled React component?

I read the answers on this question but none is similar to my set up:
What are controlled components and uncontrolled components?
I have a parent component and many children as inputs. Each input has a defaultValue that is set using a prop received from the parent and the validation of the input is performed on onBlur. This is because the validation is asynchronous, so onChange would slow down the app like crazy.
How is this orchestration called? The traditional definition for "controlled" seems to be an input which updates on every onChange, while an "uncontrolled" input is one which manages its own internal state, which is later accessed via a ref. My set up seems to fall short of both, sitting somewhere in the middle - or not?
Update: Here's a CodeSandbox.
If I understand your setup correctly, your inputs are uncontrolled, because their state is held in the DOM rather than in React state. Validation is a separate concern, which can happen synchronously or asynchronously. You can let React state hold the values whatever you do for validation. Note that most of the time you don't want to prevent the input from even having an invalid value - you just want to ensure that the user can't submit the form while the values are invalid. Thus you can have an onChange handler to set some value on state as in the following:
<input type="text"
value={this.state.myValue}
onChange={val => this.setState({myValue: val},
()=> this validateMyValue(this.state.myValue))}} />
this.validateMyValue could be asynchronous, and do whatever is required if validation fails. That would be a controlled component doing what you want.

Custom validation for custom fields in React

I have a form, which is populated using various types of question fields (e.g. text input, email, number, radio box, tags, custom inputs ). These field types are fetched dynamically based on prior choices of user on a previous form.
Now, I have to validate the different form fields when user submits the form using React. The issue is that I can't simply check the value attribute of the fields, since some fields are complex and we get the value after applying some calculation, replacing-non-numbers, or some fields may have radio buttons and corresponding text inputs etc. How can I go about this validation in React? My general structure is this:
<form>
{ this.props.questions.map((question, index) => {
return <Question key={index} data={question} validationError={this.state.validationErrors[question.name]} />
})}
</form>
<button onClick={this.validateFields}>Submit</button>
Is it possible to loop through components in validateFields method of this component class? Or I need to loop through the html nodes that are rendered in the final HTML?
Earlier I was doing this using jQuery and was looping through the question div elements and applying custom validation rules depending on the question type (stored in a data attribute).
Now, I am not sure what is the correct way to do this in React.
You're applying jQuery (and vanilla JS) patterns of thinking to React. I suggest to stop considering you have DOM in any form. No DOM, no components list either, do not touch it or React will be a pain instead of help.
All the data you want to have must be in state. That's the purpose of this library.
So, in your case it is better to go this way:
1) Implement onChange event in Question and other field components. Regardless of how complex they are, your could stream their data into a signle argument, aren't you?
2) Add onChange handler in your form with something like
onChange={value =>
this.setState({
fieldValues: {
[index]: value
}
})
}
3) Populate fieldValues like this:
constructor(props) {
super(props);
this.state = {
fieldValues: props.questions,
};
}
And voila - all the form data are already in this.state.fieldValues, ready for any ongoing usage.
Surprised? So I was, when I first been understanding user input in React. Check this section in React docs for the source of the idea: https://reactjs.org/docs/forms.html#controlled-components

React semantic UI: How to set focus for input field of dropdown element

Is it possible to initially set focus to an input field of an Dropdown element?
<Dropdown
name={name}
placeholder='Select type'
search
searchInput={{ type: 'text' }}
selection
onChange={this.handleChange}
options={options}
/>
So the user should be able to start typing/searching without the need of clicking on the dropdown input field...
If I understand your question correctly, you want to give your Dropdown component focus when your content is loaded?
If that is indeed the case, then you want to make use of Refs. See the following for a detailed example:
Refs and the DOM
In particular:
When to Use Refs
There are a few good use cases for refs:
Managing focus, text selection, or media playback.
Triggering imperative animations.
Integrating with third-party DOM libraries.

Modify Redux Form Value and Trigger Onchange

I have a simple hidden input field in my React Redux-Form and the value of the field is set by some Google Tag Manager code that basically does document.getElementById('gtm_field').value = 'some value'
The onchange event never gets fired and therefore the value of the form field never gets set in my Redux store. What is the recommended way to approach this problem? Note that I can modify the GTM code that is added to the page do trigger HTML element events, but it has to be added 'outside' the context of my React app.
Is there a simple way to set the value of a redux-form input field from 'external' JS?
You should use the function change() in redux-form props, it could change the value of a field in the Redux store. The usage like this:
handleChange() {
this.props.change(field:String, value:any)
}

Categories

Resources