File not uploading when uploading with AJAX using symfoy - javascript

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'}) }}

Related

Laravel 7 - Uncaught ReferenceError: Dropzone is not defined

I have a form that uses Dropzone for uploading images. The framework used is Laravel 7. The images are uploaded regularly to the store and inserted into the database, but in the console I get the following error:
Uncaught ReferenceError: Dropzone is not defined.
Also the page does not refresh or redirect.
View
<form data-single="true" data-file-types="image/jpeg|image/png|image/jpg" action="inserisci_avatar" class="dropzone " id="dropzone-avatar" method="POST" >
#csrf
<div class="fallback">
<input name="avatar" type="file" />
</div>
<div class="dz-message" data-dz-message>
<div class="text-lg font-medium">Trascina il tuo avatar qui.</div>
<div class="text-gray-600"> Oppure clicca e seleziona il file </div>
</div>
</form>
<script>
window.onload = function() {
//Dropzone.autoDiscover = false;
Dropzone.options.dropzoneAvatar = {
maxFilesize: 12,
acceptedFiles: ".jpeg,.jpg,.png,.gif",
addRemoveLinks: true,
timeout: 5000,
success: function(file, response)
{
console.log(response);
},
error: function(file, response)
{
return false;
}
};
};
</script>
Controller:
public function ins_avatar(Request $request)
{
$azienda = Auth::user();
if ($request->hasFile('file')) {
$id = $azienda->azienda->id;
$ins_avatar = Azienda::find($id);
if ($ins_avatar->avatar != null) {
$cancella = $ins_avatar->avatar;
Storage::delete('public/' . $cancella);
}
$path = $request->file('file')->store('uploads/avatar', 'public');
$ins_avatar->avatar = $path;
$ins_avatar->save();
$ok = 'ok';
return response()->json(['success' => $ok]);
} else {
return back()->with('avatar modificato', 'Nessuna immagine è stata caricata');
}
}
Grazie

Vue 1 class binding returning always false

I am working on this Laravel Social Network Script and it uses Vue 1.0.26.
My objetive is to bind the class connected or disconnected according to the user status which is true or false. I created a Laravel API to get the user status:
Controller (Laravel):
// $id = User id - https://www.mysite.uy/api/v1/status/{userid}
public function getUserStatus($id)
{
$active = false;
$open_session = \App\OpenSession::where('user_id', $id)->first();
if($open_session) {
if(Carbon::parse($open_session->created_at)->diffInSeconds(Carbon::parse($open_session->expires)) < 86400 && $open_session->active > 0) {
$active = true;
}
}
return response()->json($active);
}
This works fine from the URL, it returns true or false, but then here is some view.blade.php:
<li class="list-group-item" v-for="conversation in conversations.data" v-if="conversation.user"> <!-- Conversaciones -->
<a href="#" #click.prevent="showChatBox(conversation)">
<div class="media">
<div class="media-left">
<img v-bind:src="conversation.user.avatar" alt="images">
</div>
<div class="media-body">
<h4 class="media-heading">
#{{ conversation.user.name }}
<i v-bind:class="getUserStatus(conversation.user.id)"></i> <!-- <-- look at here -->
</h4>
<span class="pull-right active-ago" v-if="message">
<time class="microtime" datetime="#{{ message.created_at }}" title="#{{ message.created_at }}">
#{{ message.created_at }}
</time>
</span>
</div>
</div>
</a>
</li>
This block is being displayed as <i></i> on the HTML when using the getUserStatus() method on computed:
<h4 class="media-heading">
#{{ conversation.user.name }}
<i v-bind:class="getUserStatus(conversation.user.id)"></i> <!-- <-- look at here -->
</h4>
And this displays <i class="status disconnected"></i> even when the response.data is true and I check it with console.log(response.data == true):
<h4 class="media-heading">
#{{ conversation.user.name }}
<i v-bind:class="['status', getUserStatus(conversation.user.id) ? 'connected' : 'disconnected' ]"></i>
</h4>
And here is the Vue stuff:
data: {
status: {
on: 'connected',
off: 'disconnected'
},
},
created: {
...
},
methods: {
getUserStatus: function(userid)
{
this.$http.post(base_url + 'api/v1/status/' + userid).then(function(response) {
if(response.data == 'true') {
return true;
} else {
return false;
}
});
},
},
computed: {
/*getUserStatus: function(userid)
{
this.$http.post(base_url + 'api/v1/status/' + userid).then(function(response) {
return {
status: true,
connected: response.data == 'true',
disconnected: response.data == 'false'
}
});
}*/
}
I only have one of the methods "working", but I switch them. I am reading this guide but I get this is for Vue 2.
Ok, I made it work by adding a default variable in data and changing it later:
data: {
...
userStatus: {},
}
And in the method. As you can see I made some irrelevant changes on the Controller side.
methods: {
getUserStatus: function(userid)
{
var userStatus = this.$http.post(base_url + 'api/v1/status/' + userid).then(function(response) {
this.userStatus = JSON.parse(response.data);
});
return this.userStatus.status;
},
...
}
And in the HTML side I use:
<h4 class="media-heading">
#{{ conversation.user.name }}
<i class="status connected" v-bind:class="[ 'status', getUserStatus(conversation.user.id) ? 'connected' : 'disconnected' ]"></i>
</h4>
Now I have a different issue: The function seems to run repeteadly so the status are constantly changing. All the other functions runs once.

Show success/error message on dropzone file upload

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

Symfony2: manually submit a form without class via AJAX

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)

Dropzone.js and symfony formbuilder

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.

Categories

Resources