I'm trying to handle dropzone.js to work correct with my entity symfony formbuilder.
Everything works properly if I'm using simple <input type="file" id="form_file" name="form[file]">
BUT if I'm using dropzone.js I get this difference in my POST:
How I can handle it?
This is my js for it:
Dropzone.options.myAwesomeDropzone = {
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 25,
maxFiles: 25,
init: function() {
var myDropzone = this;
$("#submit-all").click(function (e) {
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
}
);
}
}
My form file looks like:
<form id="my-awesome-dropzone" class="wizard-big dropzone" action="{{ path('add') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form.name, {'attr': { 'class': 'form-control' } }) }}
<div class="row">
<div class="dropzone-previews"></div>
<div class="fallback">
{{ form_widget(form.file, {'attr': { 'class': 'cotam' } }) }}
</div>
</div>
<button type="submit" id="submit-all" class="btn">Upload the file</button>
{{ form_rest(form) }}
</form>
And my controller:
public function addAction(Request $Request) {
$photo = new Photo();
$form = $this->createFormBuilder($photo)
->add('name')
->add('file')
->getForm();
$form->handleRequest($Request);
if ($form->isValid() && $Request->isMethod('POST')) {
$em = $this->getDoctrine()->getManager();
$em->persist($photo);
$em->flush();
$this->redirect($this->generateUrl('add'));
}
return $this->render('MyBundle::add.html.twig', array(
'form' => $form->createView()
));
}
Could You help me?
Ok I found the answer... It was simple as possible..
You need to just add a option:
paramName: "form[file]"
To Your dropzone configuration.
Related
Im using DropzoneJS to upload Multiple files on my project.
I save the files in "wwwroot/ODIUpload" with new names using "Guid" in my "GeneratorClass" & Save the images name in OrderDetailImagesUpload Table in Database.
Now, after uploading the images, i want to if the user press delete button, the image will be deleted in "wwwroot/ODIUpload".
How can I do that?
View & Save Location Pic
View Code:
<div class="col-md-12">
<div id="dropzone ">
<form action="/Package/Design/#Model.OrderDetailID" method="post" enctype="multipart/form-data"
id="myAwesomeDropzone" class="dropzone">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="OrderDetailID"/>
<span asp-validation-for="ImageName" class="validation-error uplood-error"></span>
#Html.AntiForgeryToken()
<div></div>
<div class=" text-center">
<span class="uploadicon"> <i class="fal fa-images"></i> </span>
<div class="dz-message needsclick">
<button type="button" class="dz-button uploadicontext"> Upload Here</button><br/>
</div>
</div>
</form>
</div>
Js Code:
<script>
function myParamName() {
return "files";
}
Dropzone.options.myAwesomeDropzone = {
paramName: myParamName, // The name that will be used to transfer the file
maxFiles: 10,
dictRemoveFile: "Delete",
maxFilesize: 100,
uploadMultiple: true,
acceptedFiles: ".jpeg,.jpg,.png",
addRemoveLinks: true,
accept: function (file, done) {
if (file.name === "justinbieber.jpg") {
done("Naha, you don't.");
}
else { done(); }
},
};
</script>
Controller:
Upload Action:
[Authorize]
[Route("Package/Design/{id}")]
[HttpPost]
public IActionResult ODetailImages(OrderDetailImagesUpload _detailImagesUpload, ICollection<IFormFile> files)
{
if (files.Count() == 0)
{
ModelState.AddModelError("ImageName", "Upload Order Pics");
return View("OrderDetailImgUpload");
}
if (ModelState.IsValid)
{
_productService.AddOrderDetailImagesUpload(_detailImagesUpload.OrderDetailID, files);
return RedirectToAction("ShowBasket");
}
return View("OrderDetailImgUpload");
}
Services:
AddOrderDetailImagesUpload Service:
public void AddOrderDetailImagesUpload(int OrderDetailID, ICollection<IFormFile> imgups)
{
if (imgups != null && imgups.Any())
{
foreach (IFormFile file in imgups)
{
if (file.IsImage())
{
OrderDetailImagesUpload ODIU = new OrderDetailImagesUpload()
{
OrderDetailID = OrderDetailID,
ImageName = Generator.GetImageName() + Path.GetExtension(file.FileName)
};
_context.Add(ODIU);
string savePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/ODIUpload",
ODIU.ImageName);
using (var stream = new FileStream(savePath, FileMode.Create))
{
file.CopyTo(stream);
}
_context.SaveChanges();
}
}
}
}
I don't know how to return the names of the images to the view and assign each of them to the delete button.
I am developing an application and i want to upload a picture using Ajax with symfony 3.4. Sorry if i am missing anything because i am new to AJAX. I am following the step from https://codepen.io/dsalvagni/pen/BLapab
I am getting the 200 response from symfony but the files doesnt upload.
Entity:
/**
* #ORM\Column(type="string", length=255)
* #var string
*/
private $image;
/**
* #Vich\UploadableField(mapping="profile_image", fileNameProperty="image")
* #var File
*/
private $imageFile;
Here is my controller:
public function testAction(Request $request)
{
$testEntry = new Test();
$form = $this->createForm(TestType::class, $testEntry);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$file = $testEntry->getImageFile();
$fileName = md5(uniqid()) . '.' . $file->guessExtension();
$photoDir = $this->container->getParameter('kernel.root_dir') . '/../web/uploads/images';
$file->move($photoDir, $fileName);
$testEntry->setImage($fileName);
$em = $this->getDoctrine()->getManager();
$em->persist($testEntry);
$em->flush();
if ($request->isXmlHttpRequest()) {
return new JsonResponse(array('message' => 'Success!', 'success' => true), 200);
}
if ($request->isMethod('POST')) {
return new JsonResponse(array('message' => 'Invalid form', 'success' => false), 400);
}
return $this->redirect($this->generateUrl('homepage'));
}
return $this->render('#Alumni/Default/test.html.twig',
['form' => $form->createView()]);
}
and here is my html.twig
{{ form_start(form) }}
{{ form_errors(form) }}
{{ form_row(form.name) }}
<div class="profile">
<div class="photo">
{{ form_widget(form.imageFile, {'attr': {'class': 'file-upload'}}) }}
<div class="photo__helper">
<div class="photo__frame photo__frame--circle">
<canvas class="photo__canvas"></canvas>
<div class="message is-empty">
<p class="message--desktop">Drop your photo here or browse your computer.</p>
<p class="message--mobile">Tap here to select your picture.</p>
</div>
<div class="message is-loading">
<i class="fa fa-2x fa-spin fa-spinner"></i>
</div>
<div class="message is-dragover">
<i class="fa fa-2x fa-cloud-upload"></i>
<p>Drop your photo</p>
</div>
<div class="message is-wrong-file-type">
<p>Only images allowed.</p>
<p class="message--desktop">Drop your photo here or browse your computer.</p>
<p class="message--mobile">Tap here to select your picture.</p>
</div>
<div class="message is-wrong-image-size">
<p>Your photo must be larger than 350px.</p>
</div>
</div>
</div>
<div class="photo__options hide">
<div class="photo__zoom">
<input type="range" class="zoom-handler">
</div><i class="fa fa-trash"></i>
</div>
<button type="button" id="uploadBtn">Upload</button>
</div>
</div>
{{ form_row(form.submit, { 'label': 'Submit me' }) }}
{{ form_end(form) }}
here is my route
test:
path: /test
defaults: {_controller: AlumniBundle:Default:test}
here is my js
$(function() {
/**
* DEMO
*/
var p = new profilePicture('.profile', null,
{
imageHelper: true,
onRemove: function (type) {
$('.preview').hide().attr('src','');
},
onError: function (type) {
console.log('Error type: ' + type);
}
});
$('#uploadBtn').on('click', function() {
var image = p.getAsDataURL();
$.post("/test", { image: image });
});
and i am getting 200 response but i cannot locate the file:
Many thanks in advance for your help
It won't upload because your function isn't sending any file.
It's just sending the file name at most.
The Function
function ajaxSubmit(node) {
$.ajax({
type: node.attr("method"), // Method on form tag
url: node.attr("action"), // Action on form tag
enctype: "multipart/form-data", //needed to upload files
data: new FormData(node[0]), // The form content
processData: false,
contentType: false,
cache: false
}).done(function(response, status, xhr) {
console.info(response);
}).fail(function(request, status, error) {
console.error(request);
console.error(status);
console.error(error);
});
}
The Action
$(body).on("submit", ".ajs", function(e) {
e.preventDefault(); // Prevent default HTML behavior
ajaxSubmit($(this)); //Handle submit with AJAX
});
The View
// Add 'ajs' class to forms that should be submited with AJAX
{{ form_start(form, {'class': 'ajs'}) }}
I am using dropzone file upload, when I return success / error from controller, how do I show it on my view file..
View file ,
<div class="box-body">
#if ( $errors->count() > 0 )
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
{{ $message = 'Please select csv file only.' }}
</div>
#endif
{!! Form::open([ 'url' => 'admin/reports','class' => 'dropzone', 'id' => 'reportfile' ]) !!}
{!! csrf_field() !!}
<div class="col-md-12">
<h3 style="text-align : center">Select File</h3>
</div>
<button type="submit" class="btn btn-primary">Upload Report</button>
{!! Form::close() !!}
</div>
Controller Code
if ($request->hasFile('file')) {
$file = Input::file('file');
$validator = Validator::make(
[
'file' => $file,
'extension' => strtolower($file->getClientOriginalExtension()),
], [
'file' => 'required',
'extension' => 'required|in:csv',
]
);
if ($validator->fails()) {
return Response::json('error', 400);
}
JS Code
<script>
window.onload = function () {
Dropzone.options.reportfile = {
paramName: "file",
maxFilesize: 2,
error: function (file, response) {
alert('hiii')
},
init: function () {
this.on("addedfile", function (file) {
alert("Added file.");
});
},
accept: function (file, done) {
alert('hi')
if (file.name == "justinbieber.jpg") {
done("Naha, you don't.");
}
}
};
};
</script>
Not even alert is working...any help is much appreciated..Thanks
You should listen the events, and trigger whether it is success or not
Dropzone.options.uploadWidget = {
init: function() {
this.on('success', function( file, resp ){
alert("Success");
});
},
...
};
Note : You can have the other breakpoints as suggested here
We have an old website where I have implemented a form that is sent by AngularJS to a PHP script and after processing an email message get sent. If the form is not valid the PHP script returns a JSON with the validation errors. Since we already use Symfony for some other applications (REST APIs), I thought it would be nice to reimplement my plain PHP script in Symfony.
For the sake of simplicity I put only a small but relevant fragment of my code. This is what I have:
HTML (ng-app is bound on body tag, not shown here):
<form name="infoscreenForm" class="form-horizontal" enctype="multipart/form-data" ng-controller="FormController">
<div class="form-group">
<div class="col-lg-1 control-label">*</div>
<div class="col-lg-11 input-group">
<input type="text" class="form-control" id="contact_person"
name="contact_person" ng-model="formData.contactPerson"
placeholder="Kontaktperson">
</div>
<span class="text-warning" ng-show="errors.contactPerson">
{{ errors.contactPerson }}
</span>
</div>
<div class="form-group">
<div class="col-lg-1 control-label">*</div>
<div class="col-lg-11 input-group">
<span class="input-group-addon">#</span>
<input type="email" class="form-control" id="email" name="email"
ng-model="formData.email" placeholder="E-Mail">
</div>
<span class="text-warning" ng-show="errors.email">
{{ errors.email }}
</span>
</div>
<div class="form-group">
<div class="col-lg-1 control-label"> </div>
<div class="col-lg-11 input-group">
<input type="file" class="form-control" id="file" name="file"
file-model="formData.file"
accept="application/pdf,image/jpeg,image/png">
</div>
<span class="text-warning" ng-show="errors.file">
{{ errors.file }}
</span>
</div>
<div class="form-group">
<button type="submit" class="btn btn-default" id="submit"
name="submit" ng-click="submitForm()">
Formular absenden
</button>
</div>
</form>
JS:
var app = angular.module('InfoscreenApp', []);
app.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function () {
scope.$apply(function () {
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
app.factory('multipartForm', ['$http', function ($http) {
return {
post : function (uploadUrl, data) {
var fd = new FormData();
for (var key in data) {
fd.append(key, data[key]);
}
return $http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers : { 'Content-Type': undefined }
});
}
};
}]);
app.controller('FormController', ['$scope', 'multipartForm', function ($scope, multipartForm) {
$scope.formData = {};
$scope.submitForm = function () {
var uploadUrl = 'http://localhost:8000/infoscreen';
multipartForm.post(uploadUrl, $scope.formData)
.then(function (data) {
console.log(data);
if (data.success) {
$scope.message = data.data.message;
console.log(data.data.message);
} else {
$scope.errors = data.data.errors;
}
});
};
}]);
With the plain PHP script everything works fine. Here is what I tried to do in Symfony:
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Email;
class DefaultController extends Controller
{
/**
* #Route("/infoscreen", name="infoscreen")
*/
public function infoscreenAction(Request $request)
{
$defaultData = array('message' => 'infoscreenForm');
$form = $this->createFormBuilder($defaultData)
->add('contactPerson', TextType::class, array(
'constraints' => array(
new NotBlank(),
)
))
->add('email', EmailType::class, array(
'constraints' => array(
new NotBlank(),
new Email(),
)
))
->add('file', FileType::class)
->add('submit', SubmitType::class)
->getForm();
;
$form->submit($request->request->get($form->getName()));
$data = $form->getData();
if ($form->isValid()) {
echo 'Alles ok';
// send an email
}
$errors = array();
$validation = $this->get('validator')->validate($form);
foreach ($validation as $error) {
$errors[$error->getPropertyPath()] = $error->getMessage();
}
$response = new Response();
$response->setContent(json_encode(array(
'form_data' => $data,
'errors' => $errors,
)));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
}
CSRF is disabled in config.yml. The form is not bound to an entity class. After submitting the form I get the following object in the console:
{
data: Object,
status: 200,
config: Object,
statusText: "OK"
}
The important part is in data: Object:
{
form_data: {
contactPerson: null,
email: null,
message: "infoscreenForm",
file: null
},
errors : {
children[contactPerson].data = "This value should not be blank",
children[email].data = "This value should not be blank"
}
}
This happens when I submit the form with some values entered in the fields. It seems that the submitted data is not bound to the form in the controller. I'm probably missing something, but I stuck here and have no idea how to proceed. I tried with $form->bind($request), $form->handleRequest($request) and few other things, but it didn't work. Even if I bind the fields individually, I still don't get their values in the form.
Can somebody please help me.
Thanks in advance.
Try
$this->get('form.factory')->createNamedBuilder(null, 'form', $defaultData)
instead of
$this->createFormBuilder($defaultData)
I have a php form which requires two submit buttons. One to submit the form using ajax(which works), but now i need to add another button which will complete the sale.
My current approach is adding another submit button to form & trying to distinguish between the two in javascript (which i dont know how to do).
so any help here would be appreciated or any othher recommended approach please.
php form
<form id="bidForm">
<div class="form-group" id="divCheckbox" style="visibility: hidden">
{{ Form::hidden('item_id', $item->id) }}
{{ Form::hidden('user_id', Auth::User()->id) }}
</div>
<!-- bid -->
<div class="form-group" style="width: 100px" style="text-align: right">
{{Form::label('bid_amount', 'Bid:') }}
{{Form::text('bid_amount', null, ['class' => 'form-control', 'id' => 'bid-amount']) }}
</div>
<!-- max bid
<div class="form-group">
{{Form::label('max_bid', 'Max Bid:') }}
{{Form::text('max_bid', null, ['class' => 'form-control']) }}
</div> -->
{{ Form::hidden('permission', "userr") }}
<!-- submit`` -->
<div class="form-group">
{{Form::submit('Bid', ['class' => 'btn btn-primary', 'id' => 'submit']) }}
</div>
{{ Form::close() }}
script
$( "#bidForm" ).submit(function( e ) {
// Async submit a form's input.
e.preventDefault();
var form = $(this);
var method = 'POST';
var url= "/items/" + {{ $item->id }};
//var bid = $("#winner").innerHTML().val();
var bid = document.getElementById("winner").innerHTML;
var new_bid = $("#bid-amount").val();
bigger = (new_bid > bid) ? true : false;
console.log('');
if(bigger){
$.ajax({
type: method,
url: url,
data: form.serialize(),
action:"http://localhost:8000/items" + {{ $item->id }},
success: function(data) {
console.log("AJAX request was successfull");
$('#bid-amount').val('');
},
failure: function() {
console.log("AJAX request failed");
}
});
}
else{
window.alert("This is not a high bid");
}
});
An implementation of ClickCoder's answer here is would solve your problem.
EDIT:
Ok so you could do the following with your submit buttons:
{{Form::submit('Bid', ['class' => 'btn btn-primary submit', 'id' => 'bid']) }}
{{Form::submit('Complete Sale', ['class' => 'btn btn-primary submit', 'id' => 'sale']) }}
and then distinguish between them in JS like so:
$('.submit').on('click', function(e){
//When a submit is clicked
e.preventDefault();
//prevent submit button default action
var $token = $(this).attr('id');
//get the id of the submit
if($token == 'bid'){
//If the clicked submit has an id of bid - Do Ajax stuff
}else{
//Do sale stuff
}
});