Django render on the same template - ajax

I try to create a pagination, so i use a some lines of JS to send data, i catch it correctly (and can print it in the console) and i see they are different but my render never change.
Console.log:
[15/Mar/2017 14:30:09] "POST /index/ HTTP/1.1" 200 15320
[POST] 2
[15/Mar/2017 14:30:10] "POST /index/ HTTP/1.1" 200 9003
[POST] 3
[15/Mar/2017 14:30:10] "POST /index/ HTTP/1.1" 200 9003
[POST] 4
[15/Mar/2017 14:30:16] "POST /index/ HTTP/1.1" 200 9003
[POST] 1
Template.html:
<p> THIS IS THE PAGE {{ page }} </p>
<div class="col-xs-12 center">
<ul class="pagination" >
<li><a href="#" value={{ page|add:"-1" }}>«</a></li>
<li><a href="#" value=0>1</a></li>
<li><a href="#" value=1>2</a></li>
<li><a href="#" value=2>3</a></li>
<li><a href="#" value=3>4</a></li>
<li><a href="#" value=4>5</a></li>
<li><a href="#" value={{ page|add:"1" }}>»</a></li>
</ul>
</div>
<script language="javascript">
$('ul.pagination li a').on('click', function(e){
e.preventDefault();
$.ajax({
url: '/index/',
type: 'POST',
headers: {'X-CSRFToken': '{{ csrf_token }}'},
data: {'page': $(this).attr('value')},
contentType: 'application/x-www-form-urlencoded; charset=utf-8',
processData: true,
});
})
</script>
Views.py:
def index(request):
print("[POST]",request.POST.get('page'))
page = int(request.POST.get('page', 0))
return render(request, "site/index.html",
{'page': page})
So I think if i'm on /index/ i can't do a new render of index with new variable (and new render with this variable as well) ?
Do you have an idea when i can do that ?
EDIT: i add console log prove i catch the value of page with JS.

To print the page already format in HTML by the Django rendering engine, use the function in ajax to to overwrite a the current page : $("html").html(response); so just adjust the javascript part.
<script language="javascript">
$('ul.pagination li a').on('click', function(e){
e.preventDefault();
$.ajax({
url: '/index/',
type: 'POST',
headers: {'X-CSRFToken': '{{ csrf_token }}'},
data: {'page': $(this).attr('value')},
'success': function(response)
{
$("body").html(response);
}
});
})
</script>

Related

How to update data on a page using ajax script?

There is a script that needs to update the data on the page in a specific div. But instead of updating, the block with the div is simply hidden and in order for it to appear again, you need to reload the page. The data comes in data, but here is $ ("# userPost" + id) .html (data); something doesn't work.
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$('.infinite-scroll').on('click', '#editPostButton', function(e) {
e.preventDefault();
var id = $(this).data('id');
var user_id = $('#userForm').val();
var form = document.getElementById('EditPostForm'+id);
var formData = new FormData(form);
// var formData = $('#EditPostForm'+id).serialize();
$.ajax({
url: "id"+user_id+"/"+id+"/edit",
type: "POST",
data: formData,
success: function(data) {
console.log(data);
$("#userPost"+id).html(data);
$("#closeButton"+id).click();
},
error: function() {
console.log('error');
},
processData: false,
contentType: false,
});
});
And div
<div id="userPost{{$post->id}}">
#if($post->img)
<div>
<img src="{{$post->img}}" class="img-fluid">
</div>
#endif
<br>
#if($post->title)
<div class=" mr-1 mb-3 titleleft">
<h5 style="color: black"><b>{{$post->title}}</b></h5>
</div>
#endif
#if($post->message)
<div class="text-muted text-small margins" style="white-space: pre-wrap;">{{mb_strimwidth($post->message, 0, 600, " . . . Read more")}}</div>
#endif
#if($post->videoPost)
<div class="embed-responsive embed-responsive-16by9 mt-4 mb-2">
<iframe class="embed-responsive-item" src="{{$post->videoPost}}" allowfullscreen></iframe>
</div>
#endif
</div>
Try doing this way:
$("#userPost"+id).load(url);
or
$("#userPost"+id).html(data).load(url);

Redirect to same ajax page after reload or form submission with old input data

I have a dashboard with some side menus. Each menus loads a page through ajax call after it is clicked.
By default when dashboard is loaded it loads the page, there is also a "dashboard" menu to switch between others like profile and add student.
But if I am at profile page and I refresh It goes back to dashboard page. Also if I try to add student by filling the form and if the form has any error it goes back to dashboard again with all old input data lost.
Web.php
Route::prefix('admin')->group(function(){
Route::get('/dashboard','AdminController#dashboard')->name('admin.dashboard');
Route::get('/login', 'Auth\AdminLoginController#showLoginForm')->name('admin.login');
Route::post('/login', 'Auth\AdminLoginController#login')->name('admin.login.submit');
Route::post('/add_student','AdminController#add_student');
Route::middleware('ajax')->group(function(){
Route::get('/summary','AdminController#summary')->name('admin.summary');
Route::get('/profile', 'AdminController#profile')->name('admin.profile');
Route::get('/add_student_form','AdminController#add_student_form')->name('admin.add_student');
});
});
AdminController.php
public function add_student_form(){
return view('admin.add_student');
}
public function add_student(Request $request)
{
$this->validate($request,[
'name'=>'required|string',
'course_id'=>'required',
'dob'=>'required|date',
'gender'=>'required|string',
'category'=>'required|string',
'qualification'=>'required|string',
'fathername'=>'required|string',
'mothername'=>'required|string',
'mob_no'=>'required|string|max:10',
'address'=>'required|string',
'email'=>'required|email',
'PIN'=>'required|string|max:6',
]);
$student = new Student;
$student->name = $request['name'];
$student->roll_no ='NITTI'.rand(10000,99999);
$student->password = Hash::make($student['mob']);
$student->fees = new StudentFees;
$student->fees->paid_fees = $request['paid_fees'];
$student->fees->balance_fees = 7000;
$student->detail = new StudentDetail;
$student->detail->course_id = $request['course_id'];
$student->detail->gender = $request['gender'];
$student->detail->category = $request['category'];
$student->detail->qualification = $request['qualification'];
$student->detail->fathername = $request['fathername'];
$student->detail->mothername = $request['mothername'];
$student->detail->mob_no = $request['mob_no'];
$student->detail->email = $request['email'] ;
$student->detail->address = $request['address'];
$student->detail->PIN=$request['PIN'];
$student->detail->dob = $request['dob'];
$student->push();
return redirect()->back();
}
add_student.blade.php
<form action="/admin/add_student" method="POST">
#csrf
//It has all the fields here and a submit button
</form>
dashboard.blade.php
<div class="container-fluid">
<div class="row">
<div class="col-2 sidebar">
<img src="{{asset('/img/admin.jpg')}}" class="fit-image">
<p class="text-center">{{Auth::user()->name}}</p>
<hr>
<ul class="list-group">
<li class="list-group-item" id="summary">Dashboard</li>
<li class="list-group-item" id="admin_profile">Profile
</li>
<li class="list-group-item" id="students">Students <i class="fas fa-angle-right ml-5"></i>
<ul class="sidenav list-group">
<li class="list-group-item" id="add_student">Add Student</li>
<li class="list-group-item" id="viewall">View All </li>
</ul></li>
</ul>
</div>
<div class="col-10 dashboard" id="admin">
</div>
</div>
</div>
dashboard.js
$(document).ready(function(){
$.ajax({
url:'/admin/summary',
type: "GET",
success: function(data){
$data = $(data);
$('#admin').html($data).fadeIn();
}
});
});
$(document).on('click','#summary', function(){
$.ajax({
url:'/admin/summary',
type: "GET",
success: function(data){
$data = $(data);
$('#admin').html($data).fadeIn();
}
});
});
$(document).on('click','#admin_profile', function(){
$.ajax({
url:'/admin/profile',
type: "GET",
success: function(data){
$data = $(data);
$('#admin').html($data).fadeIn();
}
});
});
$(document).on('click','#add_student', function(){
$.ajax({
url:'/admin/add_student_form',
type: "GET",
success: function(data){
$data = $(data); produced
$('#admin').html($data).fadeIn();
}
});
});
I tried to redirect()->back->withInput('the fields');, but it didn't work.
If there is better way to load the pages which holds the same page after reloading or form submission I would welcome that.
You could use ajax form posting.
I rewrote code to abstract ajax load.
JS:
$(document).ready(function(){
//load summary by default
loadPage('summary');
//load on click menu item
$(document).on('click','.menu-item', function(){
loadPage($(this).attr('data-page'));
});
//send xcrf token in ajax header
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
//submit form
$(document).on('submit', 'form', function(){
let form = $(this);
$.ajax({
url: form.attr('action'),
type: 'POST',
dataType: 'json',
success: function(data){
if(data.page){
//load page returned in controller
loadPage(data.page);
}
},
error: function(data){
if(data.responseJSON && data.responseJSON.errors){
$.each(data.responseJSON.errors, function(key, value){
//convert laravel dotted rules to jquery selectors
key = key.replace('.', '[').replace(/\./g, '][');
if(key.indexOf('[') !== -1){
key += ']';
}
//do something with errored elements
form.find('*[name="' + key + '"]').addClass('error');
});
}
}
});
return false;
});
});
function loadPage(page){
$.ajax({
url:'/admin/' + page,
type: 'GET',
success: function(data){
$data = $(data);
$('#admin').html($data).fadeIn();
}
});
}
HTML:
Add to <head>:
<meta name="csrf-token" content="{{ csrf_token() }}">
Change sidebar menu:
<ul class="list-group">
<li class="list-group-item menu-item" data-page="summary">Dashboard</li>
<li class="list-group-item menu-item" data-page="profile">Profile</li>
<li class="list-group-item" id="students">Students <i class="fas fa-angle-right ml-5"></i>
<ul class="sidenav list-group">
<li class="list-group-item menu-item" data-page="add_student_form">Add Student</li>
<li class="list-group-item menu-item" data-page="viewall">View All </li>
</ul>
</li>
</ul>
Controller method:
Replace return redirect()->back(); with return ['page' => 'viewall'];

Using Ajax and Django conditions to display an html variable

I'm new to using Ajax calls with Django. Im trying to implement a simple Display or not display depending on the type of get called by Ajax:
Views:
def dynamic(request):
context = {}
if request.method == 'GET':
if 'backtest_type' in request.GET:
context['display_details'] = False
print ('Im not displaying')
elif 'change_val' in request.GET:
context['display_details'] = True
print ('Im displaying')
else:
context['display_details'] = False
return render(request, "demo/dynamic.html", context)
In my template:
{% extends 'demo/base.html' %}
{% block body %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<link rel="stylesheet" href="{% static 'css/dynamic.css' %}">
<script>
$(document).on('click','#id_backtest_type', function () {
console.log( $(this).val() );
$.ajax({
type: 'get',
data: {'backtest_type': 1},
success: function (data) {
console.log('data sent ' + data);
},
failure: function(data) {
alert('Got an error dude');
}
});
});
$(document).on('click','#btnClick', function () {
// console.log( $(this).val() );
$.ajax({
type: 'get',
data: {'change_val': 1},
success: function (data) {
console.log('data sent ' + data);
failure: function(data) {
alert('Got an error dude');
}
});
});
</script>
<div>
{% if display_details %}
<h1>I'm diplaying</h1>
{% endif %}
</div>
<div id="btnClick" class="col-sm-4">
<div class="btn-group btn-group-justified" role="group">
<div class="btn-group" role="group">
<button class="btn btn-secondary" type="button">Don't Display</button>
</div>
</div>
</div>
<div id="id_backtest_type" class="col-sm-4">
<div class="btn-group btn-group-justified" role="group">
<div class="btn-group" role="group">
<button class="btn btn-secondary" type="button">Display!</button>
</div>
</div>
</div>
{% endblock %}
From the console I'm sure that the get requests are being correctly sent using ajax (the get requests are being sent and the console prints the statements:
[09/Feb/2019 20:00:56] "GET /dynamic/?backtest_type=1 HTTP/1.1" 200
6530
Im displaying
However, even if the ajax call works correctly, the template doesn't end up rendering <h1>I'm diplaying</h1>. Am I misunderstanding anything about Ajax?
Thanks in advance!

Laravel Image Upload using ajax 500 Internal Server Error

I am trying to upload image using ajax in laravel 5.2.but still i am getting error 500 Internal Server Error in route.
when i am trying to upload image using ajax request the browser shown correct route path but still i am not getting reason why it still showing error to me.
HTML
<!-- CHANGE AVATAR TAB -->
<div class="tab-pane" id="tab_1_2">
<div class="uploadimagediv"></div>
{{ Form::open(array('url' => 'admin/avatar','method'=>'post','files'=>'true','id'=>'updateprofileimage')) }}
<div class="form-group">
<div class="fileinput fileinput-new" data-provides="fileinput">
<div class="fileinput-new thumbnail" style="width: 200px; height: 150px;">
<img src="http://www.placehold.it/200x150/EFEFEF/AAAAAA&text=no+image" alt=""/>
</div>
<div class="fileinput-preview fileinput-exists thumbnail" style="max-width: 200px; max-height: 150px;">
</div>
<div>
<span class="btn default btn-file">
<span class="fileinput-new">
Select image </span>
<span class="fileinput-exists">
Change </span>
<p class="text-danger" id="error_image"></p>
<input type="file" id="picture" name="picture"/>
{{--{{ Form::file('picture') }}--}}
</span>
<span class="error alert-danger">{{ $errors->first('picture') }}</span>
<a href="javascript:;" class="btn default fileinput-exists" data-dismiss="fileinput">
Remove </a>
</div>
</div>
<div class="clearfix margin-top-10">
</div>
</div>
<div class="margin-top-10">
{{Form::hidden('id', 2, ["id"=>"id"])}}
{{ Form::button('Upload',['id'=> 'updatepicture','class'=>'btn green-haze']) }}
{{--{{ Form::submit('Submit',['class' => 'btn green-haze','name'=>'changeImage']) }}--}}
<a href="javascript:;" class="btn default">
Cancel </a>
</div>
{{ Form::close() }}
</div>
<!-- END CHANGE AVATAR TAB -->
Route
Route::group(['prefix' => 'admin'], function ()
{
Route::controller('/','DashboardController');
});
Ajax
$(document).on('click', '#updatepicture', function($e)
{
$e.preventDefault();
// send an ajax request
$("#error_image").empty();
$.ajax(
{
url: 'avatar',
processData: false,
contentType: false,
type: "post",//use for update
data: new FormData($("#updateprofileimage")[0]),
success: function(data)
{
if(data.status)
{
$("#uploadimagediv").html('<div class="alert alert-success"><button type="button" class="close">×</button>'+data.message+'</div>');
window.setTimeout(function()
{
$(".alert").fadeTo(500, 0).slideUp(500, function()
{
$(this).remove();
});
}, 5000);
$('.alert .close').on("click", function(e)
{
$(this).parent().fadeTo(500, 0).slideUp(500);
});
//console.log(data);
//$("#updateprofileimage")[0].reset();
//window.location.href = "http://localhost/laravel/admin/profile";
}
else
{
errors = data.errors;
for(error in errors)
{
$("#error_"+error.title).html(error.message);
}
}
},
error: function(xhr)
{
if(xhr.status == 422)
{
errors = xhr.responseJSON;
for(error in errors)
{
$("#error_"+error).html(errors[error][0]);
}
}
}
});
});
Error is :"NetworkError: 500 Internal Server Error - http://localhost/laravel/admin/avatar"
please suggest me where i am getting wrong.
Controller is
public function postAvatar(ImageUploadRequest $request)
{
---
}
Add the below line inside <head>
<meta name="csrf-token" content="{{ csrf_token() }}">
And add the below lines before your ajax call in javascript function
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
And don't forget to give permission to your storage folder
sudo chmod -R 777 storage
In your ajax setup you have to provide x-csrf-token with the request. For your ajax request , also there is a problem with your url:
$(document).on('click', '#updatepicture', function($e)
{
$e.preventDefault();
// send an ajax request
$("#error_image").empty();
$.ajax(
{
url: "{{url('avatar')}}",
processData: false,
contentType: false,
type: "post",//use for update
data: new FormData($("#updateprofileimage")[0]),
headers: {
'X-CSRF-TOKEN': "{{ csrf_token() }}"
},
success: function(data)
{
if(data.status)
{
$("#uploadimagediv").html('<div class="alert alert-success"><button type="button" class="close">×</button>'+data.message+'</div>');
window.setTimeout(function()
{
$(".alert").fadeTo(500, 0).slideUp(500, function()
{
$(this).remove();
});
}, 5000);
$('.alert .close').on("click", function(e)
{
$(this).parent().fadeTo(500, 0).slideUp(500);
});
//console.log(data);
//$("#updateprofileimage")[0].reset();
//window.location.href = "http://localhost/laravel/admin/profile";
}
else
{
errors = data.errors;
for(error in errors)
{
$("#error_"+error.title).html(error.message);
}
}
},
error: function(xhr)
{
if(xhr.status == 422)
{
errors = xhr.responseJSON;
for(error in errors)
{
$("#error_"+error).html(errors[error][0]);
}
}
}
});
});

Bootstrap tabs - load ajax content first THEN switch tabs

I'm having troubles delaying the tab change when loading in content with ajax.
If I'm positioned in tab 0 and click on tab 1, I want the content to be loaded with ajax and when it's done, switch tab.
At the moment the tab is changed instant, which gives a blank side till my ajax content is loaded.
HTML:
<ul class="nav nav-tabs" id="tab" role="tablist">
<li class="active"><a data-toggle="tab" id="tab1" href="#container1">Information</a></li>
<li><a data-toggle="tab" id="tab2" href="#container2">Users</a></li>
</ul>
<div class="tab-content">
#*TAB1*#
<div class="tab-pane active" id="container1">
#Html.Partial("_StaticContentFromView")
</div>
#*TAB2*#
<div class="tab-pane" id="container2">
</div>
</div>
JS:
$('#tab2').click(function () {
$.ajax({
url: '/Home/Test',
type: 'GET',
dataType: 'html',
success: function (data) {
$('#container2').html(data);
}
});
});
Update 1:
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
e.target // activated tab
e.relatedTarget // previous tab
})
This event fires before tab is changed, so I can probably load the content here.
However this event is called everytime tab is changed. How can i check which tab is choosen?
e.target gives me a url, that is not good enough..
Alright found a way..
$('a[data-toggle="tab"]').on('show.bs.tab', function (e) {
var tabName = $(e.target).text(); //Get the name of the tab.
if (tabName == 'Users') {
$.ajax({
url: '/Home/Test',
type: 'GET',
async: false,
dataType: 'html',
success: function (data) {
$('#container2').html(data);
e.target // activated tab
e.relatedTarget // previous tab
}
});
}
})
It's important that you set async to false otherwise it wont work.

Resources