Я хочу сохранить счет в отношениях: поставщик и клиент. В BillForm я хочу выбрать клиента и поставщика в каждом раскрывающемся списке, взять идентификатор выбранного поставщика и идентификатор клиента из каждого раскрывающегося списка, соответственно.
Это моя модель. Bill:
const mongoose = require('mongoose');
const { Schema } = mongoose;
const billSchema = new Schema({
number: Number,
date: {type: Date, default: Date.now()},
type: String,
locale: String,
client: {
type: mongoose.Schema.Types.ObjectId,
ref: 'clients'
},
provider: {
type: mongoose.Schema.Types.ObjectId,
ref: 'providers'
},
detail: [{
quantity: Number,
product: {
code: Number,
name: String,
price: Number
},
undertotal: Number
}],
total: Number
}
);
mongoose.model('bills', billSchema);
мой почтовый маршрут in billsController:
app.post("/api/bills/client/:clientId/provider/:providerId", async (req, res) => {
const {
name,
type,
locale,
detail,
total
} = req.body;
const clientId = req.params.clientId;
const providerId = req.params.providerId;
let existingClient = await Client.findById(clientId);
if (!existingClient) {
return res.status(404).json({
message: "client not found"
});
}
let existingProvider = await Provider.findById(providerId);
if(!existingProvider){
return res.status(404).json({
message: "provider not found"
});
}
const bill = new Bill({
name,
date: new Date(),
type,
locale,
client: existingClient._id,
provider: existingProvider._id,
detail,
total
});
try {
let newBill = await bill.save();
res.status(201).send(newBill);
} catch (err) {
if (err.name === "MongoError") {
res.status(409).send(err.message);
}
console.log(err);
res.status(500).send(err);
}
});
И, наконец, внешний интерфейс, в котором я, BillForm и NewBillWithRelationShips:
BillForm.jsx
const ClientAndProvider = (params) =>{
return (<div><Redirect to=
{`/bills/newBill/client/${params.clientId}/proveedor/${params.providerId}`} /></div>)
}
componentDidMount(){
this.props.bookClientsToMakeBill();
this.props.bookProvidersToMakeBill();
}
componentWillReceiveProps = nextProps => {
// Load Contact Asynchronously
const { bill } = nextProps;
if (bill._id !== this.props.bill._id) {
// Initialize form only once
this.props.initialize(bill);
this.isUpdating = true;
}
};
constructor(props){
super(props);
this.state = {
client: '',
provider: ''
};
}
onChange = (e) =>{
this.setState({
client: e.target.value,
provider: e.target.value
})
}
render(){
const { selectedClient,selectedProvider,handleSubmit, loading, submitting, pristine,
reset } = this.props;
if (loading) {
return <span>Loading...</span>;
}
return (
<form onSubmit={handleSubmit}>
<div className="col-md-4 mb-3">
<label >Client:</label>
<select className="custom-select d-block w-100" name="bill.client" value=
{this.state.selectedClient} onChange={this.onChange.bind(this)}>
{ this.props.clientsList.map(selectedClient => {
return(
<option key={selectedClient._id} value={selectedClient._id}>
{selectedClient.name}</option>
)
})}
</select>
</div>
<div className="col-md-4 mb-3">
<label >Provider:</label>
<select className="custom-select d-block w-100" name="bill.provider" value=
{this.state.selectedProvider} onChange={this.onChange.bind(this)}>
{ this.props.providersList.map(selectedProvider => {
return(
<option key={selectedProvider._id} value=
{selectedProvider._id}>{selectedProvider.name}</option>
)
})}
</select>
</div>
{<Route path="/bills/newBill/client/:clientId/provider/:providerId" exact
strict render={({match}) =>
(
this.state.selectedClient && this.state.selectedProvider ? (<ClientAndProvider
clientId={match.params.clientId} providerId={match.params.providerId}/>)
: (<Redirect to="/bills/new" />)
)}/>}
<Link className='btn btn-light mr-2' to='/bills'>
Cancel
</Link>
<button className='btn btn-primary mr-2' type='submit'>
{this.isUpdating ? 'Update' : 'Create'}
</button>
</form>
);
}
}
function mapState(state){
return {
clientsList: state.clientsDs.clientsList,
providersList: state.providersDs.providersList
}
}
const actions = {
bookClientsForMakeBill,
bookProvidersForMakeBill
};
const selector = formValueSelector('bill')
BillForm = connect(
state =>{
const selectedClient = selector(state,'client')
const selectedProvider = selector(state,'provider')
return{
selectedClient: `${selectedClient}`,
selectedProvider: `${selectedProvider}`
}
}
)(BillForm);
BillForm = connect(mapState,actions)(BillForm);
export default reduxForm({ form: 'bill', validate: validations })(BillForm);
И наконец, NewBillWithRelationShips:
NewBillWithRelationShips.jsx
state = {
redirect: false
};
componentDidMount() {
this.props.newBill();
let {clientId} = this.props.match.params;
this.clientId = clientId;
let{providerId} = this.props.match.params;
this.providerId = providerId;
}
submit = bill => {
return this.props
.saveBillWithRelationships(bill,this.clientId,this.providerId)
.then(response => this.setState({ redirect: true }))
.catch(err => {
throw new SubmissionError(this.props.errors);
});
};
render() {
return (
<div>
<h2>New Bill</h2>
{this.state.redirect ? (
<Redirect to='/bills' />
) : (
<BillForm bill={this.props.bill} clientId = {this.props.clientId}
providerId = {this.props.providerId} onSubmit={this.submit} />
)}
</div>
);
}
}
function mapStateToProps(state) {
return {
bill: state.billsDs.bill,
errors: state.billsDs.errors
};
}
export default connect(
mapStateToProps,
{ newBill, saveBillWithRelationships }
)(NewBillWithRelationShips);
Как видите, ожидаемый результат в URL-адресе следующий: например, /bills/newBill/client/418rujrn23/provider/2344junnnhj
Но реальный результат: /bills/newBill/client/undefined/provider/undefined
Я не передаю значения идентификаторов клиентов и провайдеров из раскрывающихся списков (см. Тег select)
Что не так?