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.