Dynamically content bootstrap modal dialog from PHP Symfony2 - javascript

I'm working with bootbox to render a forms with symfony 2. So I've a one trouble when I wanna change the content dynamically I don't know how.
So this is that I wanna
I click a button that render a Form from controller embebed inside of modal dialog
<button class="btn btn-primary btn-new" data-toggle="modal" data-target="#agregarRonda">
Add My Entity
</button>
<div style="display: none;" class="modal fade" id="agregarRonda" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Add my Entity</h4>
</div>
<div class="modal-body">
{% embed "projete:MyEntity:newMyEntity.html.twig" %}
{% endembed %}
</div>
</div>
</div>
</div>
2.When I render a Form newMyentity.html.twig this has a button that redirecting to this method inside of my controller on symfony like:
public function createMyEntityAction(Request $request)
{
$user = $this->get('security.context')->getToken()->getUser();
$entity = new MyEntity();
$form = $this->createMyEntityForm($entity);
$form->handleRequest($request);
if ($form->isValid())
{
if( ifNotExist( $entity->getDescription() ) )
{
//Do the right things
}
else{
/*
* Return content to the modal dialog and don't hide modal dialog?
*/
}
}
}
So, I call a method ifNotExist to check somethings.If return false I wish to send content to the modal dialog without hide the modal dialog and modify the content.
How can I do it?
Thanks.

You can do something like this:
public function createMyEntityAction(Request $request)
{
$user = $this->get('security.context')->getToken()->getUser();
$entity = new MyEntity();
$form = $this->createMyEntityForm($entity);
if ($request->getMethod()=="POST"){
$form->handleRequest($request);
if ($form->isValid())
{
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return new Response($entity->getId(),201);
}
}
return $this->render('yourFormTemplate.html.twig', array('form' => $form->createView() );
}
Your entity:
use Symfony\Component\Validator\Constraints as Assert;
...
/**
* MyEntity
* #ORM\Entity()
* #ORM\Table()
*/
class MyEntity
{
...
/**
*
* #Assert\NotBlank(message ="Plz enter the description")
*/
private $description;
...
}
Your JS:
$('#yourAddBtnId').on('click', function(){
var $modal = $('#yourModalId')
$.get("yourURL", null, function(data) {
$modal.find('modal-body').html(data);
})
// create the modal and bind the button
$('#yourModalId').dialog({
buttons: {
success: {
label: "Save",
className: "btn-success",
callback: function() {
that = this;
var data = {};
// get the data from your form
$(that).find('input, textarea').each(function(){
data[$(this).attr('name')] = $(this).val();
})
// Post the data
$.post( "yourURL", function(data , status) {
if ( "201" === status){
$modal.modal('hide');
}
else {
$modal.find('modal-body').html(data);
}
});
}
}
});
});

Related

How to send a cropped image in formData to PHP

I have a form with several inputs. One input is a file uploader. I'm using Cropperjs. That is working fine. It produces a base64 img. I want to be able to pass this cropped preview image to a php page for processing along with other post variables as ajax formData. I'm able to pass the other $_POST variables via the submit button in php. How do I get the image to pass it?
To me it seems to not be appending to the formData or I am not asking for the right FILES var...
https://jsfiddle.net/nick1572/c6027thL/6/
HTML
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalLabel">Crop the image</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="img-container">
<img id="image" src="https://avatars0.githubusercontent.com/u/3456749">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="crop">Crop</button>
</div>
</div>
</div>
</div>
<!--end modal-->
<div class="file_drop_zone">
<div class="preview">
<img id="preview_image" accept="image/*"><!-- this is the image that needs to be passed.-->
</div><!--end preview-->
<div class="file__controls">
<label for="file_input">
<i class="fa fa-upload download_icon"></i><br>
<span class="drag__files_or">Drag File in or</span>
<span class="choose__file_btn">Choose File</span>
<input type="file" name="file" id="file_input">
</label>
</div>
</div><!--End file_uploader-->
JS
// Set the vars
var drop_zone = document.querySelector('.file_drop_zone');
var input = document.getElementById('file_input');
var image = document.getElementById('image');
var preview_image = document.getElementById('preview_image');
var preview_wrapper = document.querySelector('.preview');
var $modal = $('#modal');
var cropper;
var $submit = $('.seminar_form_submit');
var $event_form = $('.seminar_event_form');
// Create a function to read the file upload
// provided by the user.
function readFile(event) {
var url;
// File passed to FileList
var file = event.target;
// create a variable to pass in the the url.
// In this case it is the reader result. Then
// show the bootstrap modal.
var done = function (url) {
input.value = '';
image.src = url;
$modal.modal('show');
};
// Create a new File Reader instance
// for getting the result
var reader = new FileReader();
reader.onload = function() {
done(reader.result);
};
// If the event type is a 'change' then grab the
// file otherwise if the file is a 'drop'
// we get the file through the dataTransfer
if (event.type === 'change') {
reader.readAsDataURL(file.files[0]);
console.log(file.files[0]);
} else if (event.type === 'drop') {
reader.readAsDataURL(event.dataTransfer.files[0]);
}
}
// Once the modal is shown, create a new cropper instance and
// assign it to the #image div. // Once the modal is hidden
// destroy the instance for resetting cropper.
$modal.on('shown.bs.modal', function () {
/* global Cropper */
cropper = new Cropper(image, {
aspectRatio: 1,
viewMode: 0,
zoomable: true,
cropBoxMovable: true,
minContainerWidth: 100,
minContainerHeight: 100,
autoCropArea: 0.5
});
}).on('hidden.bs.modal', function () {
cropper.destroy();
cropper = null;
});
// Add listener to the crop button on the modal. If there is a cropper
// instance then set the canvas to the getCroppedCanvas function
// provided by cropperjs. We can set the dims there. We want to set the initial
// preview image src to the canvas. This is now a string in the form of
// a base64. Then hide the modal.
var crop = document.getElementById('crop');
var canvas;
var initialPreviewURL;
crop.addEventListener('click', function (crop) {
canvas = cropper.getCroppedCanvas({
width: 180,
height: 180,
fillColor: '#fff',
imageSmoothingEnabled: false,
imageSmoothingQuality: 'high'
});
initialPreviewURL = preview_image.src;
preview_image.src = canvas.toDataURL();
preview_wrapper.style.display = 'block';
$modal.modal('hide');
});
$event_form.on('submit', function(e) {
e.stopPropagation();
e.preventDefault();
var form_data = new FormData(document.getElementById('my_form'));
canvas.toBlob(function(blob) {
form_data.append('preview_image', blob);
for (var key of form_data.entries()) {
console.log(key);
}
});
$.ajax({
url: 'create_event.php',
data: form_data,
cache: false,
processData: false,
contentType: false,
type: 'POST',
success: function() {
console.log('success');
},
error: function () {
preview_image.src = initialPreviewURL;
},
complete: function () {
console.log('completed');
}
});
});
I am able to see the output in the console. By using a for loop on the entries
["preview_image", File]
If I error_log on the php. The output only shows 'error here' it does not show the preview_image
error_log("error here");
error_log($_FILES['preview_image']);
Here is the output from the Network > Response tab on the php page.
var_dump($_POST); or var_dump($_FILES);
array(9) {
["subject"]=>
string(12) "Persons Name"
["details"]=>
string(39) "Designer and wanna be web developer...."
["event-title"]=>
string(21) "This is another title"
["location"]=>
string(58) "This place"
["aux"]=>
string(13) "George Carlin"
["start-date"]=>
string(10) "2019-10-18"
["start-time"]=>
string(5) "08:00"
["end-date"]=>
string(10) "2019-10-18"
["end-time"]=>
string(5) "09:00"
}
array(1) {
["file"]=>
array(5) {
["name"]=>
string(0) ""
["type"]=>
string(0) ""
["tmp_name"]=>
string(0) ""
["error"]=>
int(4)
["size"]=>
int(0)
}
thanks!!
Well after digging around for a few days I went with just adding a hidden field and setting that value as the base64 string. I already had a ton of PHP error handling scripts already so I removed the ajax call. Now, the base64 string gets passed along with the POST array.

Copy jQuery object to modal, then hide or show, then display

I want to display a footer within a modal only when user is logged in (via ajax).
I want the footer itself to be contained in the main HTML page, which can be over-ridden by other users.
So I have a hidden container holding it on the main page:
<div style="display:none" id="signupModalFooterContainer">
<div class="modal__footer btn-group" class="signupModalFooter">
You are logged in
</div>
</div>
I can add it to the popup content:
popUpContent += $('#signupModalFooterContainer').html();
How can I make the browser re-draw the modal content between running $('.signupModalFooter').show() or $('.signupModalFooter').hide() after adding it to the window?
Empty and Replace your html content before showing
if (loggedin == 'yes') {
$('.signupModalFooter').html('You are logged in');
} else {
$('.signupModalFooter').html('');
}
$('.signupModalFooter').show();
What I ended up doing, recommended by a mentor, is to
create a "state object" which tracks the "logged in" state as well as holding various other attributes.
create two render() functions, one to render the modal main content and one to render the inner content, when events are showing feedback within the modal.
The state object looks like this:
var my_state = {
logged_in: (wordpress_i18n_key.loggedIn == 1) ? true : false,
message: undefined,
inner_container: '<div id="innerDiv"></div>',
other_attribute: undefined,
// Grab the login form from a hidden container in the DOM
login_form: $('#LogInContainer').html(),
initialize: function(target){
this.target = $(target).attr("href");
this.siteID = $(target).attr('data-someData');
}
}
Where wordpress_i18n_key.loggedIn is either a 0 or 1 that wordpress prints out to the HTML page in a <script></script> tag to make php variables available to javascript.
This function renders the main modal content:
function render_modal(){
var message = (my_state.message ? '<p>'+my_state.message+'</p>' : '');
my_state.wrapper = '<div class="modal__wrapper" id="wrapperDiv">';
if (my_state.logged_in){
my_state.wrapper += my_state.header;
my_state.wrapper += '<div class="modal__content" id="contentDiv">'+message+my_state.signup_button+'</div>';
my_state.wrapper += my_state.footer;
} else {
my_state.wrapper += my_state.header;
my_state.wrapper += '<div class="modal__content" id="contentDiv">'+message+my_state.login_form+'</div>';
}
my_state.wrapper += '</div>';
if ($('#cboxLoadedContent')) {
$('#cboxLoadedContent').html(my_state.wrapper);
}
my_state.message = undefined;
}
Where #cboxLoadedContent is the main container in the colorbox.js modal.
Then for activity that should show feedback within part of the modal:
function render_inner_modal_activity(){
my_state.content = '';
$('#innerDiv').html = '';
if (my_state.action == 'processing'){
my_state.content += my_state.spinner;
} else if (my_state.action == 'login_failed') {
my_state.content += my_state.message;
my_state.content += my_state.login_form;
} else {
// login, sign_up_form, etc
my_state.content += my_state.message;
}
if ($('#innerDiv')) {
$('#innerDiv').html(my_state.content);
}
}
When user clicks modal page button:
/**
* Initial Modal Window to Register for a Class
*
* Also leads to options to login and sign-up with API
*
*/
$(document).on('click', "a[data-target=someButton]", function (ev) {
ev.preventDefault();
my_state.initialize(this);
render_mbo_modal();
$("#modalContainer").load(my_state.target, function () {
$.colorbox({html: my_state.wrapper, href: my_state.target});
$("#modalContainer").colorbox();
});
});
Filling out the modal form, feedback stays in the modal:
/**
* Sign In to API
*/
$(document).on('submit', 'form[id="login"]', function (ev) {
ev.preventDefault();
var form = $(this);
var formData = form.serializeArray();
var result = { };
$.each($('form').serializeArray(), function() {
result[this.name] = this.value;
});
$.ajax({
dataType: 'json',
url: mz_mindbody_schedule.ajaxurl,
type: form.attr('method'),
context: this, // So we have access to form data within ajax results
data: {
action: 'client_log_in',
form: form.serialize()
},
beforeSend: function() {
my_state.action = 'processing';
render_mbo_modal_activity();
},
success: function(json) {
var formData = $(this).serializeArray();
var result = { };
$.each($('form').serializeArray(), function() {
result[this.name] = this.value;
});
if (json.type == "success") {
my_state.logged_in = true;
my_state.action = 'login';
my_state.message = json.message;
render_mbo_modal();
} else {
my_state.action = 'login_failed';
my_state.message = json.message;
render_mbo_modal_activity();
}
} // ./ Ajax Success
}) // End Ajax
.fail(function (json) {
my_state.message = 'ERROR SIGNING IN';
render_mbo_modal_activity();
console.log(json);
}); // End Fail
});
And this is the outer container the modal initially references:
<div class="modal fade" id="modalContainer" tabindex="-1" role="dialog" aria-labelledby="mzSmallModalLabel" aria-hidden="true"></div>

Symfony2 & AJAX - How to integrate an AJAX call with the toggleClass() method

I have a list of News objects. Every news has a startDate and an expireDate. Also, every news has a state property.
If the expireDate is < date('now) then state is set to 0. state is set to 1 when expireDate > date('now).
When I render the list, for the news with state == 1 I have a toggle switch (On & Off) to activate or deactivate the news (state == 1 or state == 0 respectively). I can't get the toggle work properly.
This is my html for the buttons and my jQuery function that gives the active class to the button the user clicks:
//news.html.twig
{% if news.state == 1 %}
<div class="btn-group btn-toggle">
<button class="btn btn-xs btn-primary active">On</button>
<button class="btn btn-xs btn-default ">Off</button>
</div>
{% endif %}
<script type="text/javascript">
$('.btn-toggle').click(function() {
$(this).find('.btn').toggleClass('active');
if ($(this).find('.btn-primary').length > 0) {
$(this).find('.btn').toggleClass('btn-primary');
}
$(this).find('.btn').toggleClass('btn-default');
});
</script>
I need to integrate here the $.post call to set the state for the news when the user clicks the button.
I have in mind something like this:
$.post('{{ path('set_news_state') }}', {id: 'news.id'}, function(response) {
if (response.code == 100 && response.success){
//do something
}
}, "json");
These would be my controller:
/**
* #Route("/setNewsState/{id}", name = "set_news_state")
* #Method("POST")
**/
public function setNewsOn(Request $request, $id) {
if ($request->isXMLHttpRequest()) {
return new JsonResponse(array('data' => 'this is a json response'));
}
$repository = $this->getDoctrine()->getRepository('AppBundle:News');
$news = $repository->findOneById($id);
if ($news->getState() == 0) {
$news->setState(1);
} else {
$news->setState(0);
}
$em = $this->getDoctrine()->getManager();
$em->persist($news);
$em->flush();
return new Response();
}
How can I integrate the $.post call in my already working jQuery function?
Thanks!
You're on the right track, but it's even simpler than what you have. If you POST to the correct URL, you can get the New's entity's ID from the route parameter.
// news.html.twig
// You can supply a second argument to path() to fill in the route params.
$.post("{{ path('set_news_state', {'id': news.id}) }}").done(function(response) {
if (response.status === 'ok') {
// ...
}
});
Then in your controller
/**
* #Route("/setNewsState/{id}", name="set_news_state")
* #Method("POST")
**/
public function setNewsOn($id) {
$em = $this->getDoctrine()->getManager();
$news= $em->find('AppBundle:News', $id);
if ($news->getState() == 0) {
$news->setState(1);
} else {
$news->setState(0);
}
$em->persist($news);
$em->flush();
return new JsonResponse(array(
'status' => 'ok'
));
}
Last thing,
$news = $repository->findOneById($id); is unnecessary because find() searches for ID by default (well, not really, it searches for the primary key by default, but that's almost always going to be ID).
news = $repository->find($id); is the same, but cleaner.

How do i include the csrf_token to dropzone Post request (Django)

Allright this is resolved. Just editing in case anyone runs into the same problem.
Add the Code posted in Comment marked as answer in the same javascript file.
When defining
var myDropzone = new Dropzone(...
...//More stuff here
headers:{
'X-CSRFToken' : csrftoken
}
And thats it.
So im getting a 403 Forbidden when submitting the POST request through dropzone.js to django.Django displayed the message saying that I didnt include the CSRF token, but I don't know how to actually include it if im not using a form in the HTML.
document_form.html
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}Add files{% endblock %}
{% block files %}
<div class="container-fluid" id="container-dropzone">
<div id="actions" class="row">
<div class="col-lg-7">
<span class="btn btn-success file-input-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
</span>
<button type="submit" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel upload</span>
</button>
</div>
<div class="col-lg-5">
<!-- file processing state -->
<span class="fileupload-process">
<div id="total-progress" class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%;" data-dz-uploadprogress></div>
</div>
</span>
</div>
</div>
<div class="table table-striped files" id="previews">
<div id="template" class="file-row">
<div>
<span class="preview"><img data-dz-thumbnail></span>
</div>
<div>
<p class="name" data-dz-name></p>
<strong class="error text-danger" data-dz-errormessage></strong>
</div>
<div>
<p class="size" data-dz-size></p>
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0"
aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%"
data-dz-uploadprogress>
</div>
</div>
</div>
<div>
<button class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start</span>
</button>
<button data-dz-remove class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
<button data-dz-remove class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
</div>
</div> <!-- /table-striped -->
</div> <!-- /container-fluid -->
</div>
{% endblock %}
{% block dz-add %}
<script src="{% static 'js/dropzone-bootstrap.js' %}"></script>
{% endblock %}
dropzone-bootstrap.js
$(function() {
var previewNode = document.querySelector("#template");
previewNode.id = "";
var previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
var myDropzone = new Dropzone(document.querySelector("#container-dropzone") , {
url: "/dashby/files/add/", //url to make the request to.
thumbnailWidth: 80,
thumbnailHeight: 80,
parallelUploads: 20,
previewTemplate: previewTemplate,
autoQueue: false,
previewsContainer: "#previews",
clickable: ".file-input-button",
headers: { // Tried to apply the token this way but no success.
'X-CSRFToken': $('meta[name="token"]').attr('content')
}
});
myDropzone.on("addedfile", function(file){
file.previewElement.querySelector(".start").onclick = function(){
myDropzone.enqueueFile(file);
};
});
myDropzone.on("totaluploadprogress", function(progress){
document.querySelector("#total-progress .progress-bar").style.width = progress + "%";
});
myDropzone.on("sending", function(file){
// Show total progress on start and disable START button.
document.querySelector("#total-progress").style.opacity = "1";
file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
});
// Hide progress bar when complete.
myDropzone.on("queuecomplete", function(progress){
document.querySelector("#total-progress").style.opacity = "0";
});
// Setup buttons for every file.
document.querySelector("#actions .start").onclick = function(){
myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
};
document.querySelector("#actions .cancel").onclick = function(){
myDropzone.removeAllFiles(true);
};
});
In my base.html im adding all the required files (dropzone, jquery, bootstrap and my custom javascript file)
For the django form handling:
views.py
class DocumentCreate(CreateView):
model = Document
fields = ['file']
def form_valid(self, form):
self.object = form.save()
data = {'status': 'success'}
response = JSONResponse(data, mimetype =
response_mimetype(self.request))
return response
My "Document" model
class Document(models.Model):
file = models.FileField(upload_to = 'files/',
validators=[validate_file_type])
uploaded_at = models.DateTimeField(auto_now_add = True)
extension = models.CharField(max_length = 30, blank = True)
thumbnail = models.ImageField(blank = True, null = True)
def clean(self):
self.file.seek(0)
self.extension = self.file.name.split('/')[-1].split('.')[-1]
if self.extension == 'xlsx' or self.extension == 'xls':
self.thumbnail = 'xlsx.png'
elif self.extension == 'pptx' or self.extension == 'ppt':
self.thumbnail = 'pptx.png'
elif self.extension == 'docx' or self.extension == 'doc':
self.thumbnail = 'docx.png'
def delete(self, *args, **kwargs):
#delete file from /media/files
self.file.delete(save = False)
#call parent delete method.
super().delete(*args, **kwargs)
#Redirect to file list page.
def get_absolute_url(self):
return reverse('dashby-files:files')
def __str__(self):
#cut the 'files/'
return self.file.name.split('/')[-1]
class Meta():
#order by upload_date descending
#for bootstrap grid system. (start left side)
ordering = ['-uploaded_at']
I created a Json response to handle the dropzone.
response.py
from django.http import HttpResponse
import json
MIMEANY = '*/*'
MIMEJSON = 'application/json'
MIMETEXT = 'text/plain'
# Integrating Dropzone.js with Django.
def response_mimetype(request):
can_json = MIMEJSON in request.META['HTTP_ACCEPT']
can_json |= MIMEANY in request.META['HTTP_ACCEPT']
return MIMEJSON if can_json else MIMETEXT
# Custom HttpResponse
class JSONResponse(HttpResponse):
def __init__(self, obj='', json_opts=None, mimetype=MIMEJSON,
*args, **kwargs):
json_opts = json_opts if isinstance(json_opts, dict) else {}
content = json.dumps(obj, **json_opts)
super(JSONResponse, self).__init__(content, mimetype,
*args, **kwargs)
I've been stuck with this problem for a day now, so decided to ask for help here as I havn't been able to find one.
Thanks to anyone that takes the time to read and for any help/tips that I can get.
I have just figured this out, all you need to do is add this to your dropzone config:
headers: {'X-CSRFToken': '{{ csrf_token }}'},
good luck!
just place {% csrf_token %} anywhere in your Html file . it's automatically add
<input type="hidden" name="csrfmiddlewaretoken" value="**************" />
Before sending data to the server just add extra field csrf_token which value is $("input[name='csrfmiddlewaretoken']").val();
Django’s docs have a reference for this:
While [a special parameter] can be used for AJAX POST requests, it has some inconveniences: you have to remember to pass the CSRF token in as POST data with every POST request. For this reason, there is an alternative method: on each XMLHttpRequest, set a custom X-CSRFToken header to the value of the CSRF token. This is often easier, because many JavaScript frameworks provide hooks that allow headers to be set on every request.
[…]
Acquiring the token is straightforward:
// using jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
[…]
Finally, you’ll have to actually set the header on your AJAX request, while protecting the CSRF token from being sent to other domains using settings.crossDomain in jQuery 1.5.1 and newer:
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
If you run these two code blocks before you start to make requests, it should Just Work™.
In summary, just use this code block:
// from https://docs.djangoproject.com/en/1.10/ref/csrf/ via http://stackoverflow.com/a/39776325/5244995.
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
The docs recommend getting the CSRF token from the cookie, not the DOM. Try that.
While this is an old thread, I thought I'd share the solution that worked for me.
var myDropzone = $("#file-upload").dropzone({
url: "/dashboard/api/v1/upload/",
// addRemoveLinks : true,
maxFilesize: 5,
dictResponseError: 'Error uploading file!',
headers: {'X-CSRFToken': window.CSRF_TOKEN},
success: (file, response) => {
console.log(JSON.parse(file.xhr.response));
}
});

Return a modal confirmation box in a JsonResult from controller if a condition

Hi everyone i have the following situation: I have a view in which I have a save button that is serializing a form and sending it by Ajax to a JsonResult in the Controller. Inside this JsonResult I'm adding/editing tables in the database. My question is if is possible to return a confirmation box to the view if a certain condition exists. Bellow is my code.
Thanks in the advance :)
This is the javascript in my view that is sending the form-data to the controller by ajax.
<script>
function submitForm() {
$.ajax({
type: 'POST',
url: '#Url.Action("UpdateEvent", "EventCalendar")',
data: $('#UpdateEventForm').serialize(),
success: function (eventoId) {
$('#modal-edit-event').modal('hide');
$('#calendar').fullCalendar('refetchEvents');
}
});
}
This is my Controller code that is receiving the form-data:
public JsonResult UpdateEvent(.........)
{
List<Guid> usersChanged = new List<Guid>();
.
.
.
if(usersChanged.Count() > 0)
{
//Here is where i want to call a confirmation box
}
.
.
.
return Json(eventId, JsonRequestBehavior.AllowGet);
}
}
Yes it is possible. All you have to do is, return the HTML markup needed to show in the modal dialog.
Here, i am using the RenderRazorViewToString method (from the Ben Lesh's answer onRender a view as a string)
public string RenderRazorViewToString(string viewName, object model)
{
ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext,
viewName);
var viewContext = new ViewContext(ControllerContext, viewResult.View,
ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
Now, you just need to call this method as needed to get the string version of your viewresult
public ActionResult UpdateEvent()
{
if (SomeConditionHere)
{
var modalMarkup = RenderRazorViewToString("MyModalView", null);
return Json(new { status = "failed", data = modalMarkup },
JsonRequestBehavior.AllowGet);
}
return Json(new { status = "success", eventId = 123 }, JsonRequestBehavior.AllowGet);
}
Assuming you have a view called MyModalView.cshtml which has the markup needed for the bootstrap modal dialog as below
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
<h2>Modal content</h2>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
Make sure your ajax call's success event callback method is checking the json data coming back and based on the status property value, use the data /eventId as needed.
success: function (res) {
$("#myModal").remove();
if (res.status === "failed") {
$('<div id="myModal" class="modal fade"><div class="modal-dialog" role="document">'
+res.data
+'</div></div>')
.modal();
} else {
alert("eventId is : "+ res.eventId);
}
}

Categories