I want to have a Map with a draggable marker that determines both x and y fields.
<Fields names={['x', 'y']} component={Map} />
When the marker is dropped to a new location on the map, how do I tell redux-form what the new x and y values are?
http://redux-form.com/6.5.0/docs/faq/CustomComponent.md/
const renderMap = props => (
<DragDrop
image={props.image}
currentValue={{
x: props.x.input.value,
y: props.y.input.value,
}}
thingsChanged={coords => {
props.x.input.onChange(coords.x);
props.y.input.onChange(coords.y);
}} />
)
<Fields
names={['x', 'y']}
component={renderMap}
image={this.state.image} />
Related
I’m using react-bootstrap, but with bootstrap v3, because that’s the bootstrap version my project currently uses.
Now, I just need to have a ref from an input. In the react-bootstrap docs, it says you should use formControl’s inputRef property like this:
<FormControl inputRef={ref => { this.input = ref; }} />
But currently, I’m using a function and react hooks to build my component, instead of classes.
So I just wrote my code this way:
let inputReferencia = useRef(null);
In onFocus event, I use this statement to select the content of the input:
inputReferencia.current.select();
And, finally, this is my input, as per react-bootstrap syntax:
<FormGroup>
<FieldGroup
id="referencia"
name="referencia"
value={formValues.referencia}
type="text"
label="Referencia"
onFocus={(e) => onDescripcionReferenciaInputFocus(e)}
onChange={(e) => onInputChange(e)}
inputRef={ref => { inputReferencia = ref; }} />
</FormGroup>
As React-bootstrap suggests, this is FieldGroup:
const FieldGroup = ({ id, label, help, ...props }) => {
return (
<FormGroup controlId={id} bsSize="small">
<ControlLabel>{label}</ControlLabel>
<FormControl {...props} />
{help && <HelpBlock>{help}</HelpBlock>}
</FormGroup>
);
}
But when I try to access the ref, as in
inputReferencia.current.select()
the current property is undefined.
Of course, if I check out the ref in Chrome debugger, it was definitely initialized with something:
Can somebody help me to solve this issue?
Many thanks for your help …
According to the docs you ought to use ref instead of inputRef. This is regardless of whether you are using Bootstrap V3 or Bootstrap V4 or any other version as React-bootstrap only uses their stylesheet.
In dealing with functional components and trying to access the child element's ref on the parent when the ref variable is declared on the parent, you can opt to use forwardRef
function App() {
let inputReferencia = useRef(null);
function onDescripcionReferenciaInputFocus(e) {
console.log(`inputReferencia`, inputReferencia);
}
return (
<Container>
<FormGroup>
<FieldGroup
id="referencia"
name="referencia"
value={formValues.referencia}
type="text"
label="Referencia"
onFocus={(e) => onDescripcionReferenciaInputFocus(e)}
onChange={(e) => onInputChange(e)}
ref={inputReferencia}
/>
</FormGroup>
</Container>
);
}
const FieldGroup = React.forwardRef(({ id, label, help, ...props }, ref) => {
return (
<FormGroup controlId={id} bsSize="small">
<ControlLabel>{label}</ControlLabel>
<FormControl {...props} ref={ref} />
{help && <HelpBlock>{help}</HelpBlock>}
</FormGroup>
);
});
I am working with Redux Form and in that I am trying to set the value of Hidden Input field in a loop. But the value doesn't get submitted as the field was never touched. Is there a way to solve this or am I missing something?
const renderEmployeeFields = (fields) => {
return fields.map((e, i) => {
return (
<Field
key={e._id}
name={`employeeSchedule[${i}].employee`}
component={renderTextField}
employeeId={e._id}
label={e._id}
/>
)
})
}
const renderTextField = ({ input, label, employeeId}, autocompleteKey) =>
<Input key={`${label}-input`} autoComplete={`${autocompleteKey}-${label}`} autoFocus {...input} value={employeeId} type='hidden'/>
You have to set the value using the initialValues property (https://redux-form.com/7.4.2/docs/api/reduxform.md/#-code-initialvalues-object-lt-string-string-gt-code-optional-) so that they will be available on submit.
You don't need then the hidden input.
In a SimpleForm of an Edit view I would like to set the minimum value of the group size based on the current number of members inside.
The entity is:
group = {members: 3, size: 10}
What I'm trying to achieve looks like:
export const UserCreate = (props) => (
<Edit {...props}>
<SimpleForm>
<DisabledInput label="Members number"
source="members" />
<NumberInput label="Group size"
source="size"
validation={{min: members, required: true}} />
</SimpleForm>
</Edit>
);
This is explained in the documentation, in the Per Field Validation: Function Validator part.
In a nutshell, you define a function which will take 2 parameters: the value to validate and values which contains all the form values
I am referring to the below documentation,
Tip: The props you pass to <SimpleForm> and <TabbedForm> end up as
reduxForm() parameters. This means that, in addition to validate, you
can also pass warn or asyncValidate functions. Read the reduxForm()
documentation for details.
https://marmelab.com/admin-on-rest/CreateEdit.html#validation
I tried defining warn property at the field level as well as at the form level, but warning text doesn't get displayed. However, I do see the warning property being set correctly in the meta property of that field.
Is this a bug or am I missing something? Thanks
Example (Field level):
const isTest = val => (val === "TEST" ? "Really, TEST?" : undefined);
const PeersCreateEditInputs = (
<SimpleForm>
<TextInput source="ln" label="Name" validate={[required]} warn={isTest} />
....
Example (Form level):
const isTest = values => {
const warnings = {};
if (values.ln === "TEST") {
warnings.ln = "Hmm, still TEST?";
}
return warnings;
};
const PeersCreateEditInputs = (
<SimpleForm warn={isTest}>
<TextInput source="ln" label="Name" validate={[required]} />
...
Found it, the warning is passed but not displayed. I opened an issue on the admin-on-rest repository: https://github.com/marmelab/admin-on-rest/issues/1000
I am using Redux Form version 6.4.3 and I'm trying to validate two date fields such that the 'to' date must always be before the 'from' date.
Other examples say I ought to be able to refer to the fields array in props but there is no such array. The form state has an array called registeredFields however but those just seem to be of the form {name: 'dob', type: 'Field'}
Here is my form code
import React from 'react'
import DatePicker from 'react-bootstrap-date-picker'
import moment from 'moment'
import {Field, reduxForm} from 'redux-form'
import {Form, Row, Col, Button, FormGroup, ControlLabel, FormControl, HelpBlock} from 'react-bootstrap'
// validations
const required = value => !value ? 'This field is required' : undefined
const maxDate = max => value =>
value && moment(value).isAfter(max) ? `Must be before ${max}` : undefined
const minDate = min => value =>
value && moment(value).isBefore(min) ? `Must be after ${min}` : undefined
const renderDatepicker = ({ input, label, hint, showTodayButton, meta: { pristine, touched, warning, error } }) => {
const validationState = pristine ? null : error ? 'error' : warning ? 'warning' : null
return (
<FormGroup validationState={validationState}>
<Col componentClass={ControlLabel} sm={3}>{label}</Col>
<Col sm={3}>
<FormControl
{...input}
componentClass={DatePicker}
placeholder="DD/MM/YYYY"
dateFormat="DD/MM/YYYY"
showTodayButton={showTodayButton}/>
</Col>
{pristine && !!hint && (
<Col sm={6}>
<HelpBlock>{hint}</HelpBlock>
</Col>
)}
{touched && (
(error && (
<Col sm={6}>
<HelpBlock>{error}</HelpBlock>
</Col>)
) || (warning && (
<Col sm={6}>
<HelpBlock>{warning}</HelpBlock>
</Col>
))
)}
</FormGroup>
)}
const MyForm = props => {
const { error, handleSubmit, pristine, reset, submitting, fields } = props
console.debug('fields', fields) // fields is undefined
return (
<Form horizontal>
<Field
name="dateFrom"
component={renderDatepicker}
label="Date from"
hint="Earliest date for enquiry"
validate={[required, maxDate('where do I get the other date value from?')]}
/>
<Field
name="dateTo"
component={renderDatepicker}
label="Date to"
showTodayButton={true}
hint="Latest date for enquiry"
validate={[required, minDate('where do I get the other date value from?')]}
/>
</Form>
)
}
export default reduxForm({
form: 'MyForm',
})(MyForm)
I get the feeling I am missing something obvious since all the examples I have seen expect that the fields array to exist in the props.
It's also worth mentioning that the Field's validate function signature is validate : (value, allValues, props) => error [optional] so you actually have a reference to other fields values in field-level validation as well.
I believe you could do something like:
const maxDateValidationAdapter = (value, values) => maxDate(values.dateTo)(value);
// Alternatively, if maxDate() is used only in this form you can just change its signature
<Field
name="dateFrom"
component={renderDatepicker}
label="Date from"
hint="Earliest date for enquiry"
validate={[required, maxDateValidationAdapter]}
/>
See Field documentation (Props you can pass to Field => validate).
For Redux Form, use:
export default reduxForm({
form: 'MyForm', // a unique identifier for this form
validate, // <--- validation function given to redux-form
})(MyForm)
const validate = values => {
const errors = {}
// Here you can get all the fields in value object, use value.min or value.max
return errors
}
http://redux-form.com/6.4.3/examples/syncValidation/