A
A
Artem2020-02-27 13:27:38
React
Artem, 2020-02-27 13:27:38

How to properly form Json with nested object when submitting redux-form?

Please tell me about this issue:
there is the following redux-form to create a new employee:

import React from 'react';
import { connect } from 'react-redux';
import { Field, reduxForm, formValueSelector } from 'redux-form';
import {getEmployeesAction} from "../../../redux/actions/employeeActions";

class AssetForm extends React.Component {

    componentDidMount() {
        this.props.getEmployeesAction();
    }

    onSubmit = formValues => {
        this.props.onRenderPropSubmit(formValues);
    };

    render() {
        const {
            assetTypeValue,
            pristine,
            reset,
            submitting,
        } = this.props;

        return (
            <form onSubmit={this.props.handleSubmit(this.onSubmit)}>

                <div className="form-group">
                    <Field component={"select"} className="form-control" name="assetType" aria-describedby="assetTypeHelp">
                        <option />
                        <option value={"TYPE1"}>Тип 1</option>
                        <option value={"TYPE2"}>Тип 2</option>
                        <option value={"TYPE3"}>Тип 3</option>
                    </Field>
                    <small className="form-text text-muted" id="assetTypeHelp">Тип устройства</small>
                </div>
  
                <div className="form-group">
                    <Field component={"input"} className="form-control" type="text" name={"modelName"} aria-describedby="modelNameHelp" required />
                    <small className="form-text text-muted" id="modelNameHelp">Модель устройства</small>
                </div>

                <div className="form-group">
                    <Field component={"select"} className="form-control" name="employee" aria-describedby="employeeHelp">
                        <option />
                        {this.props.employees.map(employee => {
                            if (employee) {
                                return (
                                    <option key={employee.id} value={JSON.stringify(employee)}>{employee.fullName}</option>
                                );
                            }
                            else return null;
                        })}
                    </Field>
                    <small className="form-text text-muted" id="employeeHelp">Сотрудник</small>
                </div>

                }

                {assetTypeValue === "TYPE2" &&
                    <div>
                        <div className="form-group">
                            <Field component={"input"} className="form-control" type="text" name={"description"}
                                aria-describedby="descriptionHelp" required />
                            <small className="form-text text-muted" id="descriptionHelp">Описание</small>
                        </div>
                    </div>
                }

                <div>
                    <button type="submit" disabled={pristine || submitting}>
                        Submit
                    </button>
                    <button type="button" disabled={pristine || submitting} onClick={reset}>
                        Clear Values
                    </button>
                </div>
            </form>
        );
    }
}

const mapStateToProps = ({ employees }) => {
    return {
        employees: Object.values(employees)
    };
};

// Decorate with connect to read form values
const selector = formValueSelector('assetForm'); // <-- same as form name
AssetForm = connect(state => {
    const assetTypeValue = selector(state, 'assetType');
    return { assetTypeValue };
})(AssetForm);

export default connect(mapStateToProps, {getEmployeesAction})(reduxForm({form: 'assetForm'})(AssetForm));


There is also an employee field, where the object of the same name is loaded, which has several fields (id, fullName, phoneNumber ..). When sent, JSON is generated like this:
{
  "assetType":"TYPE1",
  "modelName":"124500000",
  
  "employee": "{
    "fullName" : "user1", 
    "position":"samplePos",
    "phoneNumber": "samplePhone"
  }"	
}

With such a request, the controller returns an error 400. And it returns 201 Created only if you send it a request of this kind:
{
  "assetType":"TYPE1",
  "modelName":"124500000",
  
  "employee": {
    "fullName" : "user1", 
    "position":"samplePos",
    "phoneNumber": "samplePhone"
  }	
}

Tell me how you can fix this form to get the correct JSON output?
Thanks in advance for your reply

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alexander Cheremkhin, 2020-02-27
@core1024

The problem is in the options value value={JSON.stringify(employee)}, in fact, you have a string (String) there.

div className="form-group">
                    <Field component={"select"} className="form-control" name="employee" aria-describedby="employeeHelp">
                        <option />
                        {this.props.employees.map(employee => {
                            if (employee) {
                                return (
                                    <option key={employee.id} value={JSON.stringify(employee)}>{employee.fullName}</option>
                                );
                            }
                            else return null;
                        })}
                    </Field>
                    <small className="form-text text-muted" id="employeeHelp">Сотрудник</small>
                </div>

Based on the documentation https://redux-form.com/8.2.2/docs/api/field.md/ You can try adding a property parserto options. Most likely this should work
<option key={employee.id} value={JSON.stringify(employee)} parse={(val, name)=>JSON.parse(val)}>{employee.fullName}</option>

However, this is a somewhat unusual way to use select. It makes more sense to set options value={employee.id}and look up the actual value in this.props.employees.find(e=>e.id === employee)before submitting the form.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question