I need some help in figuring out how to add a progress bar to my redux-form to track progress of a password field.
I'm trying to use a component that renders LinearProgress of material-ui, but can't find a good way to pass/access password value.
<Field ...
name="password"
type="password"
label={PASSWORD}
component={renderField} />
<LinearProgress
mode="determinate"
value={this.state.completed} />
this.state.completed should be computed based on the password value.
If there is a standard way to do something like this, I would appreciate a pointer.
Basically you need to
access the password value in the redux store, and
pass that value to your component to calculate some sort of a complexity score
You should use formValueSelector to retrieve the value inside mapStateToProps and then just pass it on as a prop to your component. Example:
import React, { Component } from 'react'
import { formValueSelector, reduxForm, Field } from 'redux-form'
import { connect } from 'react-redux'
class MyForm extends Component {
computePasswordComplexityScore() {
// here you obviously compute whatever score you need
const score = doSomethingWith(this.props.currentPasswordValue)
return score
}
render() {
return (
<Field ...
name="password"
type="password"
label={PASSWORD}
component={renderField} />
<LinearProgress
mode="determinate"
value={ this.computePasswordComplexityScore() } />
)
}
}
const selector = formValueSelector('MyFormName')
const mapStateToProps = state => {
const currentPasswordValue = selector('password')
return { currentPasswordValue }
}
#connect(mapStateToProps)
#reduxForm({ form: 'MyFormName' })
export default class MyFormContainer extends MyForm {}
Hope this helps!
Related
I am using redux-forms and their example has a date time picker from react-widgets. Redux-Form react-widgets example
On the example on this page, it has a link to react-widgets. I pretty much followed the example on redux-forms site and I keep getting the following error:
TypeError: Cannot read property 'oneOfType' of undefined
./node_modules/react-widgets/lib/util/localizers.js
/node_modules/react-widgets/lib/util/localizers.js:23
Before anyone asks if Redux-Forms is setup correctly, I have this working with a couple of other render fields, I'm trying to add a date picker and it just crapped out on me.
// RenderDateTimePicker.jsx
import React from 'react';
import PropTypes from 'prop-types';
import DateTimePicker from 'react-widgets/lib/DateTimePicker';
import moment from 'moment';
import momentLocaliser from 'react-widgets/lib/localizers/moment';
momentLocaliser(moment);
const RenderDateTimePicker = ({input: { onChange, value, name }, label, outercss, inputcss, showTime}) => {
return (
<div className={outercss}>
<label htmlFor={name}>{label}</label>
<DateTimePicker onChange={onChange}
className={inputcss}
format={{ raw: 'MM/dd/yyyy'}}
defaultValue={new Date()}
time={showTime}
value={!value ? null : new DateTimePicker(value)}
/>
</div>
)
}
export default RenderDateTimePicker
// Snippet of main compoent
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import RenderTextField from '../common/RenderTextField';
import RenderDateTimeField from '../common/RenderDateTimePicker';
export class SearchBar extends Component {
render() {
const { handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit}>
<Field name="startDt"
outercss="col-md-2"
inputcss="form-control form-control-sm"
label="Start Date"
component={RenderTextField}
/>
<Field name="endDt"
outercss="col-md-2"
inputcss="form-control form-control-sm"
label="End Date"
component={RenderDateTimeField}
/>
<button className="btn btn-primary">Search</button>
</form>
)
}
}
export default reduxForm({
form: 'SerchAppDeploymentForm'
})(
connect(mapStateToProps, mapDispatchToProps)(SearchBar)
);
I using Redux-Form 7.3.0. I am trying to get the values of my form in another component. I read the instruction at the website of Redux form but didn't work.
this is the code of my componenet:
import React from 'react'
import { Field, reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import { formValueSelector } from 'redux-form';
class Test extends React.Component {
render() {
console.log(this.props);
return (
<div>
test
{this.props.title}
</div>
);
}
}
const selector = formValueSelector('NewPostForm');
Test = connect(
state => ({
title: selector(state, 'title')
})
)(Test)
export default Test;
This is my form component:
import React from 'react';
import { Field, reduxForm } from 'redux-form';
class NewPost extends React.Component {
renderField(field) {
return (
<div>
<label>{field.label}</label>
<input type="text" {...field.input} />
</div>
);
}
showResults(values) {
window.alert(`You submitted:\n\n${JSON.stringify(values, null, 2)}`);
}
render() {
const { pristine, submitting, handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit(this.showResults)} >
<div>
<Field
label='Title'
name='title'
component={this.renderField}
/>
<button type='submit' disabled={submitting}>
Submit the from :)
</button>
</div>
</form>
);
}
}
export default reduxForm({ form: 'NewPostForm'})(NewPost);
but I always get
title:undefined
I found the same question here but it did not help me.
Your Test component has two imports from "redux-form". Please make it just one, like this:
import { Field, reduxForm, formValueSelector } from 'redux-form'
If your NewPost component gets unmounted at any moment, maybe by changing view or something during a navigation, the state of the form gets destroyed. You can avoid such default behavior by adding destroyOnUnmount attribute with a false value to your reduxForm wrapper:
export default reduxForm({
form: 'NewPostForm',
destroyOnUnmount: false
})(NewPost)
If this doesn't help you, please provide a better context of how you're using your components.
UPDATE: I made an example where I define 4 components:
NewPost.js: It's the form connected to the store with redux-form.
ShowPost.js: Shows what was captured (the post) by the form when you hit the submit button. This data is set to the NewPost internal state, and then it's passed as prop.
ShowPostFromSelector.js: Shows what is being captured by the form, this due to the use of the selector formValueSelector.
App.js: It's the container of the 3 components above, where the onSubmit function is defined.
Here it is: https://codesandbox.io/s/w06kn56wqk
I'm using the DatePicker module for a task manager react app. It integrates well except for the first time changing the date, it always returns an object instead of the date as expected. However it magically returns the correct output if I select another date after. Here is my code for that portion of my redux form:
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import moment from 'moment';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
class TaskForm extends Component {
constructor (props) {
super(props)
}
render() {
const { handleSubmit } = this.props;
const renderDatePicker = ({input}) => (
<div>
<DatePicker {...input} dateForm="MM/DD/YYYY" selected={input.value ? moment(input.value, 'MM/DD/YYYY') : null} />
</div>
);
return (
<div>
<form onSubmit={ handleSubmit}>
<div>
{/* Date selection */}
<label>Date:</label>
<Field name="date" component={renderDatePicker} />
</div>
<button type="submit">Save</button>
</form>
</div>
)
};
};
export default reduxForm({form: 'taskForm'})(TaskForm);
Here is the value that I console.logged out:
Thanks for the help in advance!
Moment value is an object always, to get the exact format you want, just use .format, eg:
moment(date).format('MM/DD/YYYY')
I am trying to integrate Redux-form v6 into my project, however no matter how closely I try to replicate the example code, I cannot get a working redux-form.
Everything seems to be connected properly, however the handleSubmit function does not capture any of the values from my form fields.
Any guidance on this issue would be greatly appreciated. My code is below.
Starting with the reducer, nothing seems to be the matter here.
import { reducer as formReducer } from 'redux-form';
export default combineReducers({
form: formReducer
});
Then, I use a container component to connect the form component to redux form, which decorates the form component nicely with all the Redux-form function.
CreateCompany.js
import CreateCompany from '../components/create_company';
import { reduxForm } from 'redux-form';
export default reduxForm({
form: 'company-submission'
})(CreateCompany);
The actual form then looks like this:
CreateCompany.jsx
<form onSubmit={ handleSubmit(values => {console.log("values",values)})}>
<div>
<label htmlFor="group">Group Name (Required)</label>
<Field name="group" component={FormInput} type="text"/>
</div>
<div>
<Field
name="group-type"
component={DropDownSelect}
selectOptions={this.state.groupTypes}
id="group-type"
/>
<label>Group Type</label>
</div>
<button type="submit">Log In</button>
</form>
The text input stateless functions supplied to the Field component.
FormInput.js
(Note: I had to include {...input.value} in the input tag to be able to type into the field. In the example code, only {...input} is used.)
import React from 'react';
const FormInput = ({ id, type, className, input }) => {
className = className || "";
id = id || "";
return (
<input id={id} {...input.value} type={type} className={className}/>
)
}
export default FormInput;
DropDownSelect.js
import React from 'react';
const DropDownSelect = ({ input, selectOptions, id }) => {
const renderSelectOptions = (selectOption) => (
<option key={selectOption} value={selectOption}>{selectOption}</option>
)
return (
<select id={id} {...input}>
{selectOptions.map(renderSelectOptions)}
</select>
);
}
export default DropDownSelect;
Any idea what I am doing wrong?
handleSubmit should be defined outside of you CreateCompany component and passed to it via props. Check out examples
I'm using material-ui with redux. For some reason I can't type in my input fields whenever I follow the example provided at http://redux-form.com/6.2.0/examples/material-ui/ .
After using chrome redux dev tool I noticed that the state of the inputs is changing when I type but then it's re-rendering the entire component whenever something is typed, which makes it seem like nothing is being typed. Oddly enough, this only occurs when I use the Field component, as is used in the examples. If I just use material-ui components, the form allows typing and it doesn't re render. I've included the entire code to my component. Any help is much appreciated! What am I doing wrong?
import React, { Component } from 'react'
import {Field, reduxForm} from 'redux-form'
import { TextField } from 'redux-form-material-ui'
import RaisedButton from 'material-ui/RaisedButton'
class Login extends Component {
constructor (props) {
super(props)
this.handleFormSubmit = this.handleFormSubmit.bind(this)
}
componentDidMount () {
console.log(this.refs)
this.refs.username // the Field
.getRenderedComponent() // on Field, returns ReduxFormMaterialUITextField
.getRenderedComponent() // on ReduxFormMaterialUITextField, returns TextField
.focus() // on TextField
}
handleFormSubmit ({ username, password }) {
console.log(username, password)
}
render () {
const {
handleSubmit,
pristine,
submitting,
input,
fields: { username, password }
} = this.props
return (
<div className='loginWrapper'>
<form onSubmit={handleSubmit(this.handleFormSubmit)}>
<div id='loginNotch' />
<h1 className='loginHeader'>Login</h1>
<div>
<Field
component={TextField}
name='username'
floatingLabelText='Username'
ref='username' withRef />
</div>
<div>
<Field
component={TextField}
type='password'
name='password'
floatingLabelText='Password'
ref='password' withRef />
</div>
<div>
<RaisedButton
label='Go'
primary />
</div>
</form>
</div>
)
}
}
// TODO: keep property names consistent with server
export default reduxForm({
form: 'login',
fields: ['username', 'password']
})(Login)
Update: I took a look at the docs and removed fields from the export, and it is still not working.
You can clone project from here https://bitbucket.org/kvoth3/loanpayments.git
it's just a simple login screen
Try changing your reducer to
const rootReducer = combineReducers({
form: authReducer
})
ReduxForm expects your redux state structure to be
{
form: {
formName: {}
}
}
If you need to use a different name other than form, you need to provide a getFormState(state) to the reduxForm() decorator.