I have a model called Masseur and another model MasseurImage connected with a belongsTo() relationship. I also have a form with some basic inputs and Dropzone image upload integrated. The idea is when the "Create new masseur" form is submitted, it creates a new Masseur entry in the db, and creates many MasseurImage entries (based on how many images has been added into the dropzone field).
Everything works fine, except the Masseur model is saved twice in the database after the form is submitted.
View
<form method="post" id="etCreateMasseurForm" action="{{ route('masseur.add') }}" name="etCreateMasseurForm" enctype="multipart/form-data">
#csrf
<input type="hidden" name="masseur_id" id="masseur_id">
<div class="form-group mb-3">
<label class="form-label" for="nickname">Becenév</label>
<input class="form-control" type="text" name="nickname" id="nickname" required>
</div>
<div class="form-group mb-3">
<label class="form-label" for="name">Név</label>
<input class="form-control" type="text" name="name" id="name" required>
</div>
<div id="dropzoneDragArea" class="dropzone dz-default dz-message dropzoneDragArea form-control"></div>
</form>
Controller
public function store(Request $request)
{
$masseur = Masseur::create($request->all());
if ($request->hasFile('file')) {
foreach ($request->file('file') as $file) {
$filename = $file->store('public/files/'.$masseur->id);
MasseurImage::create([
'masseur_id' => $masseur->id,
'filename' => $filename
]);
}
}
return response()->json(['status' => "success", 'masseur_id'=> $masseur->id]);
}
Javascript
Dropzone.autoDiscover = false;
let token = $('meta[name="csrf-token"]').attr('content');
$(function () {
var myDropzone = new Dropzone("div#dropzoneDragArea", {
paramName: "file",
url: "{{ route('masseur.add') }}",
addRemoveLinks: true,
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 100,
maxFiles: 100,
params: {
_token: token
},
init: function () {
var myDropzone = this;
$("form[name='etCreateMasseurForm']").submit(function (event) {
event.preventDefault();
URL = $("#etCreateMasseurForm").attr('action');
formData = $('#etCreateMasseurForm').serialize();
$.ajax({
type: 'POST',
url: URL,
data: formData,
success: function (result) {
if (result.status == "success") {
var masseur_id = result.masseur_id;
$("#masseur_id").val(masseur_id);
myDropzone.processQueue();
} else {
console.log("error");
}
}
});
});
this.on('sending', function (file, xhr, formData) {
let masseur_id = document.getElementById('masseur_id').value;
formData.append('masseur_id', masseur_id);
});
this.on("success", function (file, response) {
window.location.href = "/";
});
this.on("queuecomplete", function () {
});
}
});
});
Routes
Route::post('store-masseur', [MasseurController::class, 'store'])->name('masseur.add');
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am having trouble sending multiple data types to laravel controller using ajax,
can someone help me ?.
What do I need to work in the code below:
send the text inputs, including the pdf file, via ajax to the controller,
using the submit button instead of the krajee plugin button
I'm using:
AJAX,
JQUERY,
LARAVEL,
KRAJEE INPUT FILE PUGLIN https://plugins.krajee.com/file-input
My code is based on this:
Krajee file-input submit files on form submit
DD return from controller:
array:5 [
"_token" => "TfazfXdJuIIyNe59MNx8DfJJvCl7ePkj66jsW6Vl"
"cliente_titulo" => "teste name"
"cliente_data" => "2021/12"
"cliente_cliente" => "Test"
"cliente_condominio" => "Test"
]
CONTROLLER CODE FUNCTION:
public function create(Request $request){
dd($request->all());
}
HTML CODE :
<form method="POST" id="upload" enctype="multipart/form-data">
{{ csrf_field() }}
<input id="cliente_titulo" type="text" class="form-control" name="cliente_titulo" >
<input id="cliente_cliente" type='text' name="cliente_cliente" class="form-control
autocomplete="off" >
<input id="cliente_condominio" type="text" class="form-control" name="cliente_condominio">
<input id="cliente_pdf" name="cliente_pdf" type="file" class="file-loading"
enctype="multipart/form-data" data-allowed-file-extensions='["pdf"]' >
<button id="confirm-create" type="submit" class="btn btn-success" >CREATE</button>
</form>
JS CODE:
<script>
var formData = new FormData();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
}
});
$("#cliente_pdf").on('filebatchpreupload', function(event, data, previewId, index) {
var form = data.form, files = data.files, extra = data.extra,
response = data.response, reader = data.reader;
$.each(files, function (key, value) {
if(value != null){
formData.append("pdf", value, value.name);
}
});
});
$('#upload').submit(function() {
$('#cliente_pdf').fileinput({
language: "pt-BR",
allowedFileExtensions: 'pdf',
maxFileCount: 1,
});
var model_data = $("#upload").serializeArray();
$.each(model_data,function(key,input){
formData.append(input.name,input.value);
});
$.ajax({
url: "create",
type: "POST",
datatype: "json",
data: formData,
processData: false, // tell jQuery not to process the data
contentType: false, // tell jQuery not to set contentType
success: function (data){
console.log('certo');
},
error: function (data){
console.log('error');
}
});
return false;
});
</script>
ATTEMPTS:
HTML:
<form method="POST" id="upload_form" enctype="multipart/form-data">
<input id="cliente_titulo" type="text" class="form-control" name="cliente_titulo" >
<input id='cliente_data' type='text' class="form-control" name="cliente_data" autocomplete="off" >
<input id="cliente_cliente" type='text' id_cliente="" value="" name="cliente_cliente" class="form-control {{ url_ativa('visualizarLogin') }}" data-toggle="modal" data-target="#full-colored-cliente" autocomplete="off" >
<input id="cliente_condominio" type="text" class="form-control" name="cliente_condominio" >
<input id="cliente_pdf" name="pdf" type="file" enctype="multipart/form-data" data-allowed-file-extensions='["pdf"]' required>
<button id="confirm-create" type="submit" class="btn btn-success" style="display:none"><strong>CRIAR FLIPBOOK</strong><span class="glyphicon glyphicon-ok"></span></button>
</form>
JS:
$("#cliente_pdf").fileinput({
language: "pt-BR",
uploadUrl: "{{ url('create') }}",
uploadAsync: true,
allowedFileExtensions: 'pdf',
maxFileCount: 1,
showUpload: false,
purifyHtml: true,
uploadExtraData: function(){
return {
_token: $("input[name='_token']").val();
}
},
fileActionSettings: {
showUpload: false,
},
});
$('#upload_form').on('submit',function(e){
e.preventDefault();
var formData = new FormData($(this).get(0));
$.ajax({
method: 'POST',
url: 'create',
dataType: 'json',
cache: false,
processData: false,
contentType: false,
data:formData,
beforeSend: function(){
console.log('enviando');
},
success: function(data){
console.log('sucesso');
},
cache: false,
contentType: false,
processData: false,
error:function(){
console.log('erro');
}
});
});
CONTROLLER
use Illuminate\Http\Request;
class FlipbookController {
public function create(Request $request){
dd($request->file());
or
dd($request->all());
or
dd($request->files());
or
dd($request->file('pdf'));
}
}
o unico que obetive resultado foi o
dd($request->all());
DD return from controller:
array:5 [
"_token" => "TfazfXdJuIIyNe59MNx8DfJJvCl7ePkj66jsW6Vl"
"cliente_titulo" => "teste name"
"cliente_data" => "2021/12"
"cliente_cliente" => "Test"
"cliente_condominio" => "Test"
]
I can't get the uploaded file
Where am i going wrong
You get your file object under the request files method.
$request->files(); or $request->file();
For Krajee Request look like below
$("#file-1").fileinput({
theme: 'fa',
uploadUrl: '{{ url }}',
showUpload: true,
uploadAsync: false,
uploadExtraData: function () {
return {
_token: $("input[name='_token']").val()
};
},
maxFileSize: 3000000,
});
I'm using flask as a backend and I have a button and with the use of AJAX, I am calling a view function in the flask. and I have created a son file to store some data of form.
when I fill the form and press the button my function upload gets called and it creates results and pushes it to the JSON file.
I'm returning this JSON file so that I can display it to the frontend dynamically.
but instead of data, I'm getting the whole JSON file.
upload view calls api/test to generate messages and add that messages to the data.json file
I have used ajax and a similar function in my other project but never occurred this error.
Here is my form and ajax code.
$(document).ready(function () {
$('#upload').on('click', 'button', function () {
let photos_fd = new FormData()
var img = document.getElementById('photos').files.length;
if (img == 0) {
$('#msg').html('<span style="color:red">Select at least one file</span>');
return;
}
console.log(document.getElementById('photos').files[0])
for (var x = 0; x < img; x++) {
photos_fd.append("photos[]", document.getElementById('photos').files[x]);
}
let formData = new FormData()
formData.append("email", $('#email').val());
formData.append("label", $('#label').val());
console.log("you submit the form", $('#email').val(), $('#label').val() );
$.ajax({
url: " {{url_for('upload')}} ",
dataType: 'json',
cache: false,
async: true,
contentType: false,
processData: false,
data: formData,
photos : photos_fd,
type: '',
success: function(data) {
console.log("xxxxxxx");
alert(data.keys());
// console.log("",response);
},
error: function(response) {
$("#msg").text(response.response); // display error response
}
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="contact-clean">
<form method="post" action="{{ url_for('upload') }}" enctype="multipart/form-data">
<h2 class="text-center">Upload Image</h2>
<div class="form-group">
<input class="form-control is-invalid" type="email" id='email' name="email" placeholder="Email">
</div>
<div class="form-group">
<input class="form-control" type="text" id="label" name="label" placeholder="Image Name">
</div>
<div class="form-group">
<input type="file" id="photos" name="photos[]">
</div>
<div class="form-group">
<button id ="upload" class="btn btn-primary" type="submit">UPLOAD</button>
</div>
</form>
</div>
flask view
upload
#app.route('/', methods=['POST'])
def upload():
if 'photos[]' in request.files:
photos = request.files.getlist('photos[]')
photo = photos[0]
label = request.form["label"]
email = request.form["email"]
img_formate = "." + str(photo.filename).split(".")[-1]
image = label + img_formate
photo.save(os.path.join(app.config['UPLOAD_FOLDER'], image))
result = {
label:
{
'image': image,
'email': email,
'caption': json.loads(response.text)['message']
}
}
with open('templates/data.json') as f:
data = json.load(f)
data.update(result)
with open('templates/data.json', 'w') as f:
json.dump(data, f,indent=4)
if photo.filename != '':
return data
else:
return redirect(url_for('index'))
I'm getting JSON file like this on clicking the button.
I expect the returned JSON object to be printed to the screen underneath the form, but instead, the data returned is printed directly to the browser window, which doesn't maintain the structure of 'index.html' (which has navbars and a form). I am returned this::
{
"img1":
{
"caption": " a man holding a dog in a white shirt ",
"email": "m#gmail.com",
"image": "img1.jpg"
}
}
After analyzing your code here I found error:
1. In the Second line of the script, it should be #form instead of #Upload
2. You haven't mentioned type in Ajax Call
Given bellow is modified javascript code
$(document).ready(function () {
$('#form').on('submit', function (e) {
e.preventDefault();
let photos_fd = new FormData()
var img = document.getElementById('photos').files.length;
if (img == 0) {
$('#msg').html('<span style="color:red">Select at least one file</span>');
return;
}
console.log(document.getElementById('photos').files[0])
for (var x = 0; x < img; x++) {
photos_fd.append("photos[]", document.getElementById('photos').files[x]);
}
let formData = new FormData()
formData.append("email", $('#email').val());
formData.append("label", $('#label').val());
console.log("you submit the form", $('#email').val(), $('#label').val() );
$.ajax({
url: " {{url_for('upload')}} ",
dataType: 'json',
cache: false,
async: true,
contentType: false,
processData: false,
data: formData,
photos : photos_fd,
type: 'POST',
success: function(data) {
console.log("xxxxxxx");
alert(data.keys());
// console.log("",response);
},
error: function(response) {
$("#msg").text(response.response); // display error response
}
});
});
});
I have two forms one with product details like price, description and name. And the other with images, they both have different Ajax but they send data to the same route. I want to submit them with one button. So if I click a submit button it should submit all data at once which are price, name, image etc. How can I do this if possible?
Blade file
//Form1
<form id="form1">
<input type="hidden" value="{{csrf_token()}}" id="token"/>
<label for="name">Name</label>
<input type="text" class="form-control" name="name" id="name"
placeholder="Enter product name">
<label for="price">Price</label>
<input type="text" class="form-control" name="price" id="price"
placeholder="Enter product price">
</form>
//Form2
<form id="file_form" method="post" enctype="multipart/form-data">
<input type="hidden" value="{{csrf_token()}}" id="token"/>
<label for="images">Choose Images</label>
<input id="files" type="file" class="" name="files[]" multiple />
</form>
//Submit Button
<input type='button' class="btn btn-primary" value="Submit" id="btn"/>
Javascript
//Form1 javascript
var token = $("#token").val();
$(document).ready(function(){
$("#btn").click(function(){
var url = '{{ route('product.store') }}';
var form = $('form')[0];
var formData = new FormData(form);
formData.append('_token', token);
$.ajax({
url: url,
data: formData,
type: 'POST',
cache: false,
contentType: false,
processData: false,
success:function(data){
if($.isEmptyObject(data.error)){
$("#msg").html("Product has been added successfull");
$("#msg").fadeOut(3000);
}
}
});
});
//Form 2 Javascript
$("#btn").click(function (e) {
e.preventDefault();
file_area = $('.file-area');
progressbar = $('.progress-bar');
status_bar = $('#status');
image_list = $(".image-list");
status_bar.css('display', 'block');
status_bar.html('<div class="fa-3x">' +
'<i class="fas fa-spinner fa-pulse"></i>' +
'</div>');
if (selected_files.length < 1) {
status_bar.html('<li class="error">Please select file</li>')
} else {
var data = new FormData();
data.append('_token', token);
for (var i = 0, len = selected_files.length; i < len; i++) {
data.append('files[]', selected_files[i]);
}
fiel_feild = $('#files');
$.ajax({
url: '{{ route('product.store') }}',
type: 'POST',
data: data,
contentType: false,
cache: false,
processData: false,
success: function (response) {
result = JSON.parse(response);
if (result['status'] == 'error') {
status_bar.html(result['error']);
} else if (result['status'] == 'success') {
selected_files = [];
image_list.html('');
file_area.css('display', 'none');
status_bar.html('<li class="success">File uploaded successfully.</li>');
}
}
});
return false;
}
});
I'm trying to insert data to database using ajax with Jquery. My data is inserted without ajax perfectly but when i use ajax, there is something wrong with image. it get the file null in the controller in post method.
This is my Form in the View.
<form id="InsertForm" name="InsertForm" enctype="multipart/form-data">
<div class="form-group">
<label for="Name">Name</label>
<input type="text" class="form-control" name="StudentName" id="name" />
</div>
<div class="form-group">
<label for="LastName">Last Name</label>
<input type="text" class="form-control" name="StudentLastName" id="last" />
</div>
<div class="form-group">
<label for="Address">Address</label>
<input type="text" class="form-control" name="StudentAddress" id="address" />
</div>
<div class="form-group">
<label for="Gender">Gender</label>
<input type="text" class="form-control" name="Gender" id="gender" />
</div>
<div class="form-group">
<label for="Image">Image</label>
<input type="file" class="form-control" id="StudentImage" name="StudentImage" />
</div>
<button id="saveclick" type="submit" name="save">Save</button>
</form>
This is my Script in the View for inserting data with image.
<script>
$(document).ready(function () {
$("#saveclick").click(function (e) {
var student = {
StudentName: $("#name").val(),
StudentLastName: $("#last").val(),
StudentAddress: $("#address").val(),
Gender: $("#gender").val(),
StudentImage: $("#StudentImage").val().split('\\').pop()
};
//var formdata = new FormData($('InsertForm').get(0));
//var Student= $("#InsertForm").serialize();
var jsonData = JSON.stringify(student);
alert(jsonData);
$.ajax({
type: "POST",
url: '#Url.Action("Insert", "Student", null)',// Insert Action Method in Student Controller.
contentType: "application/json; charset=utf-8",
dataType: "json",
enctype: 'multipart/form-data',
data: jsonData,
success: function (data) {
if (data.success) {
alert(data.message);
}
},
error: function (xhr) {
alert('error');
}
});
return false;
});
});
</script>
This is my Controller action Method in Student Controller.
[HttpPost]
public JsonResult Insert(Student student)
{
if (ModelState.IsValid)
{
Student stu = new Student();
stu.StudentName = student.StudentName;
stu.StudentLastName = student.StudentLastName;
stu.StudentAddress = student.StudentAddress;
stu.Gender = student.Gender;
HttpPostedFileBase file = Request.Files["StudentImage"];
file.SaveAs(HttpContext.Server.MapPath("~/Images/") + file.FileName);
stu.StudentImage = file.FileName;
db.Students.Add(stu);
db.SaveChanges();
return Json(student);
}
else
{
ModelState.AddModelError("", "Inavlid Data Inserted");
}
return Json(student);
}
Thanks if you solve my this problem.
try following
<script type="text/javascript">
$(document).ready(function () {
$("#saveclick").click(function (e) {
var data = new FormData();
var files = fileUpload.files;
fileData.append("StudentImage", files[0]);
fileData.append("StudentName",$("#name").val());
/* add all values as above one by one for LastName,Gender,Address*/
$.ajax({
type: "POST",
url: '#Url.Action("Insert", "Student", null)',// Insert Action Method in Student Controller.
contentType: "application/json; charset=utf-8",
processdata: false,
data: data,
type:"POST"
success: function (data) {
if (data.success) {
alert(data.message);
}
},
error: function (xhr) {
alert('error');
}
});
return false;
});
});
</script>
Here is the solution that solve my great problem. We need to append the ForamData in any variable.
<script>
$(document).ready(function () {
$("#saveclick").click(function (e) {
// Create FormData object
var fileData = new FormData();
var fileUpload = $("#StudentImage").get(0);
var files = fileUpload.files;
// Looping over all files and add it to FormData object
//for (var i = 0; i < files.length; i++) {
// fileData.append(files[i].name, files[i]);
//}
fileData.append("StudentImage", files[0]);
fileData.append("StudentName", $("#name").val());
fileData.append("StudentLastName", $("#last").val());
fileData.append("StudentAddress", $("#address").val());
fileData.append("Gender", $("#gender").val());
$.ajax({
type: "POST",
url: '#Url.Action("Insert", "Student", null)',
data: fileData,
processData: false,
contentType: false,
success: function (data) {
if (data.success) {
alert(data.message);
}
},
error: function (xhr) {
alert('error');
}
});
return false;
});
});
</script>
I'm using for the first time dropzone.js inside another form...so as two forms can't be nested, I removed dropzone's form:
html snippet:
<form id="addproduct" name="addproduct" action="receiveAddForm" method="post" enctype="multipart/form-data">
<fieldset class="form-horizontal">
<div class="form-group">
<div class="col-sm-2">
<small class="text-navy"><b>* Campos Obligatorios</b></small>
</div>
</div>
<div class="form-group"><label class="col-sm-2 control-label">Nombre (Modelo) *:</label>
<div class="col-sm-10"><input name="name" type="text" class="form-control"></div>
</div>
</fieldset>
<div class="dropzone dropzone-previews" id="my-awesome-dropzone"></div>
</form>
js snippet:
Dropzone.options.myAwesomeDropzone = {
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 100,
maxFiles: 3,
addRemoveLinks: true,
maxFilesize: 10,
url: 'receiveAddForm',
init: function() {
var myDropzone = this;
$("#submit_form").click(function (e) {
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
this.on("sendingmultiple", function() {
});
this.on("successmultiple", function(files, response) {
});
this.on("errormultiple", function(files, response) {
});
this.on("maxfilesexceeded", function(file){
// alert("No more files please!");
});
this.on("uploadprogress", function(file, progress) {
console.log("File progress", progress);
});
}
}
so in server side I'm getting this after echoing $_FILES:
array (size=1)
'files' =>
array (size=5)
'name' => string '' (length=0)
'type' => string '' (length=0)
'tmp_name' => string '' (length=0)
'error' => int 4
'size' => int 0
what seems to be the problem here? my php.ini is set to 1000MB in upload max file size, memory limit and so on... any help would be appreciatted!
The 'error' => int 4 means that no file has been uploaded, i think this is because you are submitting the form like if it was a regular form, if you want to include dropzone inside a regular form i don't think you can submit the form the regular way and attach to it the files dropped in the dropzone element, or at least there is no simple way to do it, one solution could be to encode the file in base64 and then add the encoded string to an input to send.
But an easy one I think is to send the form using dropzone and append the input values to the request using javascript, here generic example.
html:
<form id="addproduct">
<label>Input 1: </label>
<input type="text" name="input1">
<label>Input 2: </label>
<input type="text" name="input2">
<div id="myAwesomeDropzone" class="dropzone"></div>
</form>
<button type="button" id="submit_form">Submit</button>
js:
Dropzone.options.myAwesomeDropzone = {
url: 'receiveAddForm',
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 3,
maxFiles: 3,
init: function () {
var myDropzone = this;
$('#submit_form').on("click", function() {
myDropzone.processQueue();
});
this.on("sending", function(file, xhr, formData){
$('#addproduct').find('input').each(function() {
formData.append( $(this).attr('name'), $(this).val() );
});
});
this.on("success", function(file, response) {
console.log(response);
});
this.on("completemultiple", function(files) {
// Here goes what you want to do when the upload is done
// Redirect, reload , load content ......
});
},
};
receiveAddForm (php):
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
{
echo "RECEIVED ON SERVER: \n";
print_r($_FILES);
print_r($_POST);
}
The server file just prints the data received on the server, so you can see it in browsers console. I omitted bootstrap classes and elements only to show the relevant part, but you cand add them no problem.
to have a dropzone inside another form you can put a div in the form with class="dropzone" and convert it to dropzone element like this:
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone("#my-awesome-dropzone", {
autoProcessQueue: false,
url: "receiveAddForm",
// other options
});
then you can call the events like this:
myDropzone.on("addedfile", function(file) {
console.log("File added:", file.name);
});
jsfiddle with your form :
fiddle