I'm sending an image attribute file by ajax call. But the post api might be constantly breaking for this. I want to push the file in the image attribute array in the formData & have the successful api call.
My Api form data configuration is as shown in the following image:
When I'm checking the formData image attribute array on Console I'm getting the thing image attributes[]: [object file] as shown in the following image:
& my api is constantly failing and showing the following error:
Following is the code I'm currently stuck on:
/*NewPost.jsx */
handleSubmit = (event) => {
event.preventDefault();
console.log("Submitting")
let error = this.areThereAnyErrors();
if(!error){
let data = {};
data.description = this.state.description.value || "";
// console.log(this.state.images_attributes);
data.images_attributes = this.state.images_attributes[0] || null;
let brand_string = this.state.brand_ids[0].value;
let brands_list = this.props.auto_complete_details.brand_json;
let selected_brand = brands_list.find(function (brand) {
return brand.brand_name.toLowerCase() == brand_string.toLowerCase();
});
if(selected_brand){
this.state.brand_selected.value = selected_brand.brand_id;
}
if(this.state.brand_selected.value){
data.Brand = this.state.brand_selected.value;
} else {
// console.log(this.state.brand_ids);
data.custom_brand = this.state.brand_ids[0].value;
}
let product_string = this.state.product_ids[0].value;
let product_list = this.props.auto_complete_details.product_json;
let selected_product = product_list.find(function (product) {
return product.product_name.toLowerCase() == product_string.toLowerCase();
});
if(selected_product){
this.state.product_selected.value = selected_product.product_id;
}
if(this.state.product_selected.value){
data.Product = this.state.product_selected.value;
} else {
data.custom_product = this.state.product_ids[0].value;
}
data.Price = this.state.price.value;
this.props.onFormSubmit(data);
}
}
render() {
return(
<form onSubmit={this.handleSubmit}>
<div className={"row description new_post_desc "+error_class}>
<div className="col-md-12 col-xs-12" style={{"paddingRight":"0px"}}>
<textarea id="new_post_desc" name="description" className='new-post-description' placeholder="Share your brand story..." ref={(input) => {this.state.description = input}}/>
</div>
</div>
<div className="description">
<div className="row">
<input id="new_post_image" className={this.state.errors.images_attributes ? "error-input disp_inline": "disp_inline"} type="file" name="image" accept="image/*" ref={(input) => {this.state.images_attributes[0] = input}} />
</div>
<div className="row margin-top-10">
<div className="col-md-2 col-sm-2 col-xs-3 new_post_spacing">
<input id='autocomplete_brand' className={this.state.errors.brand_ids ? 'typeahead error-input new_post_capsules tt-hint hint_user_info' : 'typeahead new_post_capsules hint_user_info'} type="text" name="brand" placeholder="Brand" ref={(input) => {this.state.brand_ids[0] = input}}/>
<input id="brand_value_selected" style={{display: "none"}} value="" ref={(input) => {this.state.brand_selected = input}}/>
</div>
<div className="col-md-2 col-sm-2 col-xs-3 new_post_spacing">
<input id='autocomplete_product' className={this.state.errors.product_ids ? 'typeahead error-input new_post_capsules tt-hint hint_user_info' : 'typeahead new_post_capsules hint_user_info'} type="text" name="product" placeholder="Product" ref={(input) => {this.state.product_ids[0] = input}}/>
<input id="product_value_selected" style={{display: "none"}} value="" ref={(input) => {this.state.product_selected = input}} />
</div>
<div className="col-md-2 col-sm-2 col-xs-3 new_post_spacing">
<input id='autocomplete_price' className={this.state.errors.price ? 'typeahead new_post_capsules tt-hint hint_user_info error-input' : 'typeahead new_post_capsules tt-hint hint_user_info'} type="number" name="price" placeholder="Price" ref={(input) => {this.state.price = input}}/>
</div>
<div className="col-md-2 col-sm-2 col-xs-3 new_post_spacing">
<button type="submit" className="btn button-styling" style={{"outline":"none"}} disabled={this.props.new_post_creation_in_progress}>Share { loading_icon }</button>
</div>
</div>
</div>
<div className="row">
{ this.state.has_errors ? <div className="error_mesg">* Please provide required information</div> : '' }
</div>
</form>
);
}
const mapDispatchToProps = (dispatch, ownProps) => {
var that = this;
return {
dispatch,
onFormSubmit: (data) => {
dispatch(getNewPostDetails(data));
}
};
}
/* Actions/index.js */
export const getNewPostDetails = (data) => {
console.log(data);
var data_value = data;
return function(dispatch) {
var formData = new FormData();
// add assoc key values, this will be posts values
// setting form data
console.log(data_value);
//for image files
if(data_value.images_attributes) {
formData.append('images_attributes[]', $('input[type=file]')[0].files[0]);
}
//for video files
formData.append('video_attributes[]', null);
//for custom brands
if(data_value.custom_brand) {
formData.append('brand_ids[]', data_value.custom_brand);
}
//for products
if(data_value.custom_product) {
formData.append('product_ids[]', data_value.custom_product);
}
//For Price & Description
formData.append('price', data_value.Price);
formData.append('description', data_value.description);
for (let pair of formData.entries()) {
console.log(pair[0] + ': ' + pair[1]);
}
$.ajax({
type: "POST",
url: `${mainurl}/api/v1/posts`,
// headers: checkAuthHeaders(), // the main solution
formData: formData,
beforeSend: function(){
$("#new_post_desc").prop('disabled', true);
$("#autocomplete_brand").prop('disabled', true);
$("#autocomplete_product").prop('disabled', true);
$("#autocomplete_price").prop('disabled', true);
dispatch(createPostProgress(true));
},
success: function(resp) {
$('#new_post_desc').val("");
$('#new_post_image').val("");
$('#autocomplete_brand').val("");
$('#autocomplete_product').val("");
$('#autocomplete_price').val("");
$("#brand_value_selected").val("");
$("#product_value_selected").val("");
$("#new_post_desc").prop('disabled', false);
$("#autocomplete_brand").prop('disabled', false);
$("#autocomplete_product").prop('disabled', false);
$("#autocomplete_price").prop('disabled', false);
dispatch(receiveNewPostDetails(resp));
dispatch(resetNewPostFlag());
dispatch(createPostProgress(false));
},
error: function(error) {
dispatch(createPostProgress(false));
},
async: true,
cache: false,
contentType: false,
processData: false,
timeout: 60000
});
};
}
[] At the end of the name of the attribute, it usually already means that this field is an array, and the value of this field should not be an array. So try to use:
formData.append('images_attributes[]', files[0]);
formData.append('images_attributes[]', files[1]);
formData.append('images_attributes[]', files[2]);
// etc..
Instead of
formData.append('images_attributes[]', files);
The same rule applies to other fields.
Related
I have a form, and I have an input in the form, I upload several images in this input, like so:
<input type="file" name="gallery" onChange={imageHandler} required multiple />
And when I output the images in the console, it correctly displays an array of files, but when I append the images, formData.append("gallery", images); it is not saved as an array. It's saved as a File!
const [selectedFile, setSelectedFile] = useState();
const [images, setImages] = useState([]);
const token = localStorage.getItem("TOKEN");
const imageHandler = (e) => {
setImages([...images, e.target.files[0]]);
};
useEffect(() => {
images.length && console.log(images);
}, [images]);
console.log(images);
const sendDisease = async (e) => {
e.preventDefault();
console.log(images);
const form = document.getElementById("signUpForm");
const formData = new FormData(form);
formData.append("gallery", images);
console.log(formData);
try {
const api = "https://localhost/api/v1/website/disease/add";
const { data } = await axios.post(api, formData, {
headers: {
headers: { "Content-Type": "multipart/form-data" },
Authorization: `Bearer ${token}`,
},
});
toast.success(data.message, { autoClose: 15000 });
} catch (e) {
console.log(e);
toast.error(e.response.data.error, { autoClose: 15000 });
console.log(e.response.data.error);
}
};
const handleFileSelect = (event) => {
setSelectedFile(event.target.files[0]);
};
return (
<>
<div className="container">
<div className="row">
<form id="signUpForm" className="md-12">
<h2 className="text-center mb-4 font-weight-bold">Add Disease</h2>
<div className="form-row mt-4">
<div className="col-md-6 mb-3">
<label for="">Add Disease</label>
<input
type="text"
className="form-control"
name="unique_name"
required
onChange={(e) => setUniqueName(e.target.value)}
/>
</div>
<div className="col-md-6 mb-3">
<label for="">Title</label>
<input
type="text"
className="form-control"
name="title"
placeholder="Title"
onChange={(e) => setTitle(e.target.value)}
required
/>
</div>
</div>
<div className="form-row">
<div className="col-md-12 mb-3">
<label for="">Gallery</label>
<input type="file" name="gallery" onChange={imageHandler} required multiple />
</div>
</div>
<input type="file" name="image" onChange={handleFileSelect} />
</div>
<button
type="button"
className="btn btn-primary mt-4"
onClick={sendDisease}
>
Submit
</button>
</form>
</div>
</div>
</>
);
Calling new FormData(form) is enough. You don't need to call formData.append("gallery", images) as the constructor will pick on its own all the images for you. So you may not even need this images state.
The code below would log all your files if you wanna be sure about it. I also created a working Codesandbox for testing.
export default function App() {
const handleSubmit = (e) => {
e.preventDefault();
const form = document.getElementById("signUpForm");
const formData = new FormData(form);
console.log(formData.getAll("gallery"));
};
return (
<form id="signUpForm" onSubmit={handleSubmit}>
<input type="file" name="gallery" required multiple />
<button>Sumbit</button>
</form>
);
}
If it's not working, try changing formData.append("gallery", images) to the code below (it's apparently what's needed for PHP servers for example):
images.forEach((image) => {
formData.append('gallery[]', image);
});
Here in my case Am using ASP.NET Core and its working fine
images.forEach((image) => {
formData.append('images', image);
});
My Controller
[HttpPost]
public async Task<IActionResult> UpdateProfile([FromForm] UpdateProfileModel updateProfileModel)
{
try
{
await Task.CompletedTask;
return Ok("Done.");
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
My Modal
public class UpdateProfileModel
{
public List<IFormFile> Images { get; set; } = new List<IFormFile>();
}
I want to render data from API which I render it through for loop but when I'm displaying it to UI, it displays only 1 value.
Specification: - when user upload a text image, API displays text which is present in the image and name, which is the JSON data is an array so I render DetectedText value-form API using for loop but not able to display all value of DetectedText in UI so please tell me where I'm doing wrong please see the below code
import React, { Component } from 'react';
import axios from 'axios'
class Image extends Component {
constructor(props) {
super(props);
this.state = { file: '', imagePreviewUrl: '', selectedOption: '', change: [], response: [], path: [], jsonData: [], dText: [] };
}
handleSubmit(e) {
e.preventDefault();
var byteCode = this.state.imagePreviewUrl.substring((e.target.value).indexOf(',') + 23);
let url = "http://192.168.4.138/MediaAnalysisImage_Amazon/api/DetectText/DetectText";
const data = { "fileByte": byteCode }
const response = axios.post(url, data)
.then(response => {
this.setState({
change: response,
byteArr: response.data.fileByte,
jsonData: response.data.jsondata.replace(/[&\/\\#+()$"~%.'*?<>{}]/g, ''),
path: response.data.jsondata.DetectedText,
});
console.log('json detected data', this.state.jsonData)
const parseData = JSON.parse(response.data.jsondata)
let x = ""
for (let x of parseData) {
const DetectedText = x.DetectedText
this.setState({
dText: DetectedText
})
console.log('setting dtext', this.state.dText)
}
})
}
handleImageChange(e) {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () => {
this.setState({
file: file,
imagePreviewUrl: reader.result
});
}
reader.readAsDataURL(file)
}
render() {
const img = "data:image/png;base64" + ',' + this.state.byteArr
let { imagePreviewUrl } = this.state;
let $imagePreview = null;
if (imagePreviewUrl) {
$imagePreview = (<img src={imagePreviewUrl} className="img-responsive imgp" />);
} else {
$imagePreview = (<span className="previewText">Please select an Image for Preview</span>);
}
return (
<div className="wrapper">
<h2 className="text-center heading" >Text Recognization</h2>
<div className="container ">
<section className="celeb">
<form className="Fform bg-light mb-4">
<div class="form-group ">
<input className="fileInput"
type="file"
onChange={(e) => this.handleImageChange(e)} class="btn btn-secondary" />
</div>
<button className="btn btn-success"
type="submit"
onClick={(e) => this.handleSubmit(e)}>Upload Image</button>
</form>
<hr></hr>
<div className="row grid">
<div className="col-md-6">
<h3>Input Image</h3>
{$imagePreview}
</div>
<div className="col-md-6">
<h3>Output Image</h3>
<img src={img} className="img-responsive imgp" />
</div>
</div>
<div>
<hr></hr>
<h4>Description </h4>
<table className="table table-hover">
<tr>
<th ><label>Name :- </label></th>
<td>{this.state.dText}</td>
</tr>
</table>
</div>
</section>
</div>
</div>
)
}
}
export default Image;
You may change like this:
this.setState({
dText: parseData.map(x => x.DetectedText),
})
and in your render method:
<td>{ this.state.dText.map((text, index) => <div key={index}>{text}</div>) }</td>
I didn't figure out how to edit JSON data from a Put request.(it must be PUT request)
I created some inputs as you see and I need to find a way for updating/adding new credit-debit datas on JSON data differs by "to" and "from".
Also, if a "to" value added, it must decreased from total balance and if a "from" value added, it must be added to total balance.
I created a select box and an input for this (didin't connect between json and component)
My Updater component is as follows:
Component itself:
import React, { Component } from 'react';
import './Updater.scss';
import Axios from 'axios';
export default class Updater extends Component {
constructor(){
super();
this.state = {
amount: '',
description: '',
from: '',
to: '',
date: new Date()
}
}
onSubmitEdit = () => {
Axios.put('http://localhost:8080/api/balance/add',
{});
}
render() {
return (
<div className="updatercontainer">
<div className="updaterinputs">
<input className="amount" name="amount"
type="text" placeholder="Enter Amount"/>
<input className="description" name="description"
type="text" placeholder="Enter Description"/>
</div>
<div className="selectbox">
<select>
<option value="From">From</option>
<option value="To">To</option>
</select>
<input className="fromto" type="text"
name="fromto" placeholder="Enter From or To Name"/>
</div>
<div className="selectboxcontainer">
<div className="button-container">
<a href="#" onClick={this.onSubmitEdit}
className="button amount-submit">
<span></span>Update</a>
</div>
</div>
</div>
)
}
}
class Updater extends React.Component {
constructor() {
super();
this.state = {
amount: 0,
description: "",
_from: true,
_to: false,
date: new Date()
};
}
onAmountChange = e => {
this.setState({
amount: e.target.value
});
};
onDescriptionChange = e => {
this.setState({
description: e.target.value
});
};
onSelectTypeChange = e => {
console.log(e.target.value);
this.setState({
[e.target.value === "from" ? "_from" : "_to"]: true,
[e.target.value !== "from" ? "_from" : "_to"]: false
});
if(e.target.value !== "from" && (this.state.from != null || this.state.from !== "")) {
this.setState({
to: this.state.from,
from: null
});
} else if(e.target.value === "from" && (this.state.to != null || this.state.to !== "")){
this.setState({
from: this.state.to,
to: null
});
}
};
onFromToChange = (e) => {
this.setState({
[this.state._from ? "from" : "to"]: e.target.value
});
}
onSubmitEdit = () => {
Axios.put(
"https://httpbin.org/put",
{
...this.state,
},
{ headers: { "Content-Type": "application/json" } }
)
.then(response => {
// handle Response
})
.catch(err => {
// handle Error
});
};
render() {
return (
<div className="updatercontainer">
<div className="updaterinputs">
<input
onChange={this.onAmountChange}
className="amount"
name="amount"
type="text"
placeholder="Enter Amount"
/>
<input
onChange={this.onDescriptionChange}
className="description"
name="description"
type="text"
placeholder="Enter Description"
/>
</div>
<div className="selectbox">
<select onChange={this.onSelectTypeChange}>
<option value="from">From</option>
<option value="to">To</option>
</select>
<input onChange={this.onFromToChange} className="fromto" type="text"
name="fromto" placeholder="Enter From or To Name"/>
</div>
<div className="selectboxcontainer">
<div onClick={this.onSubmitEdit} className="button-container">
<a href="#" className="button amount-submit">
<span>Update</span>
</a>
</div>
</div>
</div>
);
}
}
Consider Reading More About Handling Inputs, Forms, Events
Working Sandbox!
you just need an onChange event to update the state based on the input values name
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value })
}
//On your inputs
<input
className="amount"
name="amount"
type="text"
placeholder="Enter Amount"
value={this.state.amount}
onChange={() => this.handleChange(e)}
/>
I am trying to build a contact form where an if else statement checks the validity of the email address entered, then with a nested if else checks whether the honeypot filed has a value and sends an ajaxj post request to an aws api gateway.
The ajax post runs without problem, but the outer else is always run.
Here the code:
import React from 'react'
import './style.scss'
const $ = require('jquery')
class ContactForm extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
email:'',
subject:'',
message:'',
honeypot:'',
result:'',
alertType:'',
formErrors:{
email:'',
name:'',
message:''
},
isFormValid:false,
emailValid:false,
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
const target = event.target
const value = target.value
const name = target.name
this.setState({ [name]: value })
}
handleSubmit(event) {
event.preventDefault();
var URL = "https://someaddress/";
var form =this
var data = {
name: this.cleanInput(this.state.name.trim()),
email: this.cleanInput(this.state.email.trim()),
subject: this.cleanInput(this.state.subject.trim()),
message: this.cleanInput(this.state.message.trim()),
}
this.validateField('email',data.email)
data.message = "Bilgiler şunlar:\nAdı:"+data.name+"\nEmail Adresi: "+data.email+"\nKonu:"+data.subject+"\nMesaj:"+data.message
data.subject = "[Bestpet Web Sitesinden Doldurulan Form] "+data.subject;
data.email = "info#atlaspet.com.tr";
if(this.state.emailValid ===true){
if (this.state.honeypot=== ''){
$.ajax({
type: "POST",
url: URL,
dataType: "json",
contentType: "application/json",
data: JSON.stringify(data),
success: function(){
form.setState({name:'',email:'',message:'',subject:'',result:'Form başarıyla gönderildi.',alertType:'alert alert-success'})
},
error: function () {
// show an error message
form.setState({result: 'Sorunlar oluştu. Formu gönderemedik.',alertType:'alert alert-danger'});
},
});
} else {console.log("Hi there, I guess you are not human baby");}
} else { form.setState({result: 'Lütfen girmiş olduğunuz email adresini kontrol ediniz.',alertType:'alert alert-danger'})}
}
validateField(fieldName, value) {
let fieldValidationErrors = this.state.formErrors;
let emailValid = this.state.emailValid;
;
switch (fieldName) {
case 'email':
emailValid = value.match(/^([\w.%+-]+)#([\w-]+\.)+([\w]{2,})$/i);
fieldValidationErrors.email = emailValid ? true : false;
break;
default:
break;
}
this.setState({
formErrors: fieldValidationErrors,
emailValid: fieldValidationErrors.email
}, this.validateForm);
console.log(this)
}
validateForm() {
this.setState({ isFormValid: this.state.emailValid });
}
cleanInput(input){
var search = [
'<script[^>]*?>.*?</script>', // Strip out javascript
'<[/!]*?[^<>]*?>', // Strip out HTML tags
'<style[^>]*?>.*?</style>', // Strip style tags properly
'<![sS]*?--[ \t\n\r]*>', // Strip multi-line comments
]
var text = input
// console.log(search.length)
//var output = preg_replace($search, '', input);
for (let i = 0; i < search.length; i++) {
text = text.replace(new RegExp(search[i], 'gi'), '')
}
return text
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<div>
<div className={"col-md-12 "+this.state.alertType}>{this.state.result!=='' && this.state.result}</div>
<input name="honeypot" type="text" style={{display:"none"}} value={this.state.honeypot} onChange={this.handleChange}/>
</div>
<div className="form-group">
<div className="col-md-6">
<label>
Name:
{this.state.formErrors.name!=='' && <div className="col-md-12 alert alert-danger">'Sizinle iletişim kurabilmemiz için bir isim girmelisiniz'</div>}
<input name="name" type="text" value={this.state.name} className ="form-control required" onChange={this.handleChange} />
</label>
</div>
<div className="col-md-6">
<label>
email
<input type="text" name="email" className="form-control required" value={this.state.email} onChange={this.handleChange}/>
</label>
</div>
</div>
<div className="form-group">
<div className="col-md-12">
<label>
Subject
<input type="text" name="subject" className="form-control required" value={this.state.subject} onChange={this.handleChange}/>
</label>
</div>
</div>
<div className="form-group">
<div className="col-md-12">
<label>
Message
<textarea name="message" rows="6" className="form-control required" value={this.state.message} onChange={this.handleChange}/>
</label>
</div>
</div>
<div className="form-group">
<div className="col-md-12">
<input type="submit" value="Submit" className="btn btn-sm btn-block btn-primary"/>
</div>
</div>
</form>
);
}
}
export default ContactForm
The section of code I have problems with is in handleSubmit function.
Thanks for help in advance and a happy new year to all.
I have moved the validity check to handleChange function and it is now working as intended.
Thanks a lot!
I have been trying to get my dynamic form to work in my Meteor React application.
It was all working as requested before I started add this but now I can't get it to work. I'm getting a "Uncaught TypeError: Cannot set property '0' of undefined" error. this points to this line:
{this.state.inputs.map((input, idx) => <input
This my whole code, I know it's a bit messy so any feedback is highly appreciated:
import React, { Component } from 'react';
import { Row, Col, Checkbox, Radio, ControlLabel, HelpBlock, FormGroup, FormControl, Button, Tabs, Tab } from 'react-bootstrap';
import { Bert } from 'meteor/themeteorchef:bert';
import { insertComment } from '../../../api/comments/methods';
import ReactQuill from 'react-quill';
var s3Url = null;
export default class AddSparkShanghai extends Component {
constructor(props) {
super(props);
this.createSpark = this.createSpark.bind(this);
this.onChange = this.onChange.bind(this);
this.state ={
inputs: ['input-0'],
city: '',
person: '',
location: '',
title: '',
content: [],
mediaUrls: [],
};
}
componentWillMount(){
// we create this rule both on client and server
Slingshot.fileRestrictions("myFileUploads", {
allowedFileTypes: ["image/png", "image/jpeg", "image/gif"],
maxSize: 10 * 1024 * 1024 // 10 MB (use null for unlimited)
});
}
upload(file){
var uploader = new Slingshot.Upload("myFileUploads");
uploader.send(document.getElementById('input').files[0], function (error, downloadUrl) {
if (error) {
// Log service detailed response
alert (error);
}
else {
s3Url = encodeURI(downloadUrl);
Bert.alert('File uploaded!', 'success');
Meteor.users.update(Meteor.userId(), {$push: {"profile.files": downloadUrl}});
}
});
}
createSpark(event) {
event.preventDefault();
var formData = $('#form').serializeArray()
console.log(formData);
var mediaArray = [];
if (this.mediaUrls.value == 0) {
mediaArray = [];
} else {
mediaArray.push(encodeURI(this.mediaUrls.value));
console.log(this.mediaUrl.value);
console.log(mediaArray);
}
const city = 'Shanghai';
const person = this.person.value;
const location = this.location.value;
const title = this.title.value;
const content = this.state.content;
const fileLink = s3Url;
const timestamp = parseInt(this.props.timestamp);
const mediaUrls = mediaArray;
const approved = true;
const adminSpark = true;
const createdBy = Meteor.userId();
insertComment.call({
city, person, location, title, content, fileLink, timestamp, approved, adminSpark, createdBy, mediaUrl,
}, (error) => {
if (error) {
Bert.alert(error.reason, 'danger');
} else {
Bert.alert('Spark added!', 'success');
}
});
}
onChange(html) {
this.setState ({ content: html });
}
appendInput() {
var newInput = `input-${this.state.inputs.length}`;
console.log (newInput);
this.setState({ inputs: this.state.inputs.concat([newInput]) });
}
render() {
const events = {
'text-change': delta => {
}
}
return (
<div className="background-container">
<form ref={(input) => this.sparkForm = input} onSubmit={(e) => this.createSpark(e)}>
<ControlLabel>Select your person (optional)</ControlLabel>
<select id="formControlsPerson" placeholder="Choose your person" className="form-control" ref={(input) => this.person = input}>
<option value='select'>Select your person</option>
<option value='jane'>Jane Siesta</option>
<option value='ben'>Ben Huang</option>
<option value='han'>Han Han</option>
<option value='mau'>Mau Mau</option>
<option value='void'>VOID</option>
<option value='tommy'>Tommy Hendriks</option>
<option value='gareth'>Gareth Williams</option>
<option value='gigi'>Gigi Lee</option>
</select>
<ControlLabel>Select your location (optional)</ControlLabel>
<select id="formControlsLocation" placeholder="Choose your location" className="form-control" ref={(input) => this.location = input}>
<option value='select'>Select your location</option>
<option value='shelter'>Shelter</option>
<option value='mansion'>The Mansion</option>
</select>
<ControlLabel>Title</ControlLabel>
<input type="text" label="Title" placeholder="Enter your title" className="form-control" ref={(input) => this.title = input}/>
<ControlLabel>Add Image</ControlLabel>
<div className="upload-area">
<p className="alert alert-success text-center">
<span>Click or Drag an Image Here to Upload</span>
<input type="file" id="input" className="file_bag" onChange={this.upload} />
</p>
</div>
<ControlLabel>Content</ControlLabel>
<div className='_quill'>
<ReactQuill
toolbar={false}
theme="snow"
ref='editor'
onChange={this.onChange}
events={events} />
</div>
<br />
<ControlLabel>Media (optional)</ControlLabel>
<div id="dynamicInput">
{this.state.inputs.map((input, idx) => <input
key={ input }
type="text"
label="Media"
placeholder="Add your media url"
className="form-control"
ref={(input) => this.mediaUrls[idx] = input}/> )}
</div>
<Button onClick={ () => this.appendInput() }>
Add media field
</Button>
<ControlLabel>Media (optional)</ControlLabel>
<div id="dynamicInput">
{this.state.inputs.map(input => <input key={input} type="text" label="Media" placeholder="Add your media url" className="form-control" ref={(input) => this.mediaUrl = input}/> )}
</div>
<Button onClick={ () => this.appendInput() }>
Add media field
</Button>
<Button type="submit" data-dismiss="modal">Submit</Button>
</form>
</div>
)}
}
I guess the problem is this line: ref={(input) => this.mediaUrls[idx] = input}/> )}, it seems like the value of this.mediaUrls is undefined