Ajax and Django - ajax

I have a jquery ajax code that looks like below,Its working on a delete button and a checkbox.
$(".delete-row").click(function(){
$("table
tbody").find('input[name="record"]').each(function(){
if($(this).is(":checked")){
var value = $('chk').val();
$(this).parents("tr").remove();
$.ajax({
url: "/delete/",
// type: "post", // or "get"
data: value
});
});
});
});
This jquery call should delete the checked row in a table and the added ajax call will call a django view.
My doubt is I am passing the checkbox value to django view in the above AJAX call. In this case how do django view come to know what table row to delete based on the checkbox value?
below is how my table is getting created in a for loop
{% for x in dirs %}
<tr id='this_row' style="text-align: center;">
<td>
<input type="checkbox" id="chk" value="this_row" name="record"></td>
<td>
{{ x.name }}
</td>
<td>
{{ x.created_date }}
</td>
<td>
{{ x.description }}
</td>
</tr>
{% endfor %}
below is the delete button
<button type="submit" name="erase" class="delete-row">Delete Row</button>

Just add the id of the row as value attribute to the checkbox, so your ajax will send a list of ID. Instead of this_row, add {{x.id}} the instance id
{% for x in dirs %}
<tr id='tr-{{x.id}}' style="text-align: center;">
<td><input type="checkbox" id="chk-{{x.id}}" value="{{x.id}}" name="record"></td>
<td>
{{ x.name }}</td>
<td>{{ x.created_date }}</td>
<td>{{ x.description }}</td>
</tr>
{% endfor %}
And in your ajax, you have access to it with
// send this array via ajax
$(".delete-row").click(function(){
var id_list = new Array();
$("input[name=record]:checked").each(function(){
id_lists.push($(this).val());
$(this).parent("tr").remove(); // Remove the row,
// the correct is parent() without 's', not parents()
});
// with type:'post', don't forget the csrf_token
$.ajax({
url: "/delete/",
type: "post",
data: {
id_list:id_list,
csrfmiddlewaretoken:"{{ csrf_token }}"
},
});
});
And in your view, you can retrieve the id_list containing all the selected rows with reqest.POST.getlist('id_list[]'). In case it was a GET request reqest.GET.getlist('id_list[]')

Related

How to Refresh Table after ajax request in laravel

I am working on exchange project using laravel and want to refresh my table after a
<tbody class="fixed-header">
#foreach($transactionsCustomer as $transaction)
<tr>
<td>{{ $transaction->description }}</td>
#foreach($accounts as $account)
#if($transaction->code == 0)
#if($account->currency->id==$transaction->currency_id)
<td>{{ $transaction->amount }}</td>
<td></td>
#else
<td></td>
<td></td>
#endif
#else
#if($account->currency->id==$transaction->currency_id)
<td></td>
<td>{{ $transaction->amount }}</td>
#else
<td></td>
<td></td>
#endif
#endif
#endforeach
<td><a href="{{ route('transaction.edit',$transaction->id)}}" class="btn btn-primary" >سمون</a></td>
</tr>
#endforeach
</tbody>
and here is my ajax code to store the data
$("#transaction-form").submit(function(stay){
var formdata = $(this).serialize(); // here $(this) refere to the form its submitting
$.ajax({
type: 'POST',
url: "{{ route('transaction.store') }}",
data: formdata, // here $(this) refers to the ajax object not form
success: function (data) {
$('input[type="text"],textarea').val('');
updateTable();
},
});
stay.preventDefault();
});
and here is my controller method to represent the data
public function singleCustomer(Request $request)
{
$customer = Customer::find($request->id);
$accounts = Account::where('customer_id', $request->id)->get();
$currencies = Currency::all();
$transactionsCustomer = DB::table('transactions')->
join('accounts','transactions.account_id' ,'=','accounts.id')->join('customers','accounts.customer_id','=','customers.id')->join('currencies','accounts.currency_id','=','currencies.id')->select('transactions.*','currencies.id as currency_id')->where('customers.id',$request->id)->get();
return view('transaction.index',compact('currencies','customer','accounts','transactionsCustomer'));
}
now i want to refresh my table after this ajax request
You need to separate the table in different view.
Here's the flow, you get all data from your Controller , pass it to the table view, in the main view you include the table view using #include('table-view-route').
And don't forget on your success ajax, call updateTable() which has functionality to load the table view using jquery
$("#tableContainerId").load("{{url('table-view-route')}}");

When passing data from AJAX call it returns None type

I want to pass data from AJAX call.Data wants to be the (form input data+key).
When i pass the data it returns the data that i want.But it also returns a None type value.
I want to get rid of that None type value.
Following shows my form template code.
<form action="/seq_input/" method="POST" id="MyForm"><br>
<p style="color:black;font-size:14px">These messages haven't reciever.</p>
<p style="color:black;font-size:14px">If you want you can add recivers</p>
<table id="tb1">
<tr>
<th style="display:none;">Key</th>
<th>Message</th>
<th>Reciver</th>
</tr>
{% for key,values in NullList.items%}
<tr>
<td style="display:none;">{{key}}</td>
<td>{{values}}</td>
<td><input type="text" id="{{key}}" name={{key}} value=""></td>
</tr>
{% endfor %}
</table>
<br>
<input type="submit" value="SubmitMyInputs" onclick="get_details()">
</form>
following shows the Ajax call.
var jsonArr = [];
function get_details(){
console.log("submit");
console.log(myObject);
for(var value in myObject){
var x=document.getElementById(myObject[value]).value;
jsonArr.push({
key:myObject[value],
reciever:x
});
}
alert(JSON.stringify(jsonArr));
get_ajax(jsonArr);
}
function get_ajax(jsonArr){
$.ajax({
method: 'POST',
url: $('#MyForm').attr('action'),
data: {'data': JSON.stringify(jsonArr)},
success: function(response) {
console.log(response)
alert('success');
},
error: function(response) {
console.error(response)
alert('error');
}
});
}
Following has my .py file code.
def get_seq_input(request):
if request.method == 'POST':
message = request.POST.get('data')
print(message)
the result is
[{"key":1,"reciever":"system"}] and
None
anyone have idea to getrid of this None?

Cannot read property replace of null method parameter

I started messing around with Vue.js earlier this week.
So far I created a list of MTG(a TCG) cards. The data comes from the database through an Ajax request. This all works like a charm.
What i want to do next is replace the string that contains the costs of a card e.g. something like '{1}{U}{G}' with images for the corresponding tag.
HTML:
<div v-for="(cards, key) in mainBoard" class="">
<table class="table">
<tr>
<th colspan="5">#{{ key }}</th>
</tr>
<tr>
<th>#</th>
<th>Name</th>
<th>ManaCost</th>
#if($deck->enableCommander())
<th>Commander</th>
#else
<th></th>
#endif
<th>Actions</th>
</tr>
<tr v-for="card in cards">
<td>#{{card.pivot.quantity}}</td>
<td>#{{card.name}}</td>s
<td v-html="replaceManaSymbols(card)"></td>
#if($deck->enableCommander())
<td>
<span v-if="card.pivot.commander" #click="preformMethod(card, 'removeCommander', $event)"><i class="fa fa-flag"></i></span>
<span v-else #click="preformMethod(card,'assignCommander', $event)"><i class="far fa-flag"></i></span>
</td>
#else
<td> </td>
#endif
<td>
<button #click="preformMethod(card,'removeCardFromDeck', $event)"><i class="fa fa-times-circle"></i></button>
<button #click="preformMethod(card,'plusCardInDeck', $event)"><i class="fa fa-plus-circle"></i></button>
<button #click="preformMethod(card,'minusCardInDeck', $event)"><i class="fa fa-minus-circle"></i></button>
</td>
</tr>
</table>
</div>
Vue.js
new Vue({
el: '#Itemlist',
data: {
mainBoard: [],
sideBoard: [],
},
methods:{
preformMethod(card, url){
var self = this;
var varData = {
slug: '{{ $deck->slug }}',
card: card.id,
board: card.pivot.mainboard
};
$.ajax({
url: '/vue/'+url,
data: varData,
method: 'GET',
success: function (data) {
self.mainBoard = data.mainBoard;
self.sideBoard = data.sideBoard;
},
error: function (error) {
console.log(error);
}
});
},
replaceManaSymbols(card){
var mc = card.manaCost;
var dump = mc.replace(/([}])/g, '},').split(',');
var html = '';
/**
* replace each tag with an image
*/
return html;
}
},
mounted(){
var self = this;
var varData = {
slug: '{{ $deck->slug }}'
};
$.ajax({
url: '/vue/getDeckList',
data: varData,
method: 'GET',
success: function (data) {
self.mainBoard = data.mainBoard;
self.sideBoard = data.sideBoard;
},
error: function (error) {
console.log(error);
}
});
}
})
I pass the card as a parameter to the replaceManaSymbols method. I can console.log the contents of mana without any issue. But as soon as a want to modify the string Vue throws the error TypeError: Cannot read property 'toLowerCase/split/replace' of null. I'm not really sure what's going wrong. Any idea's?
As a rule of thumb, you shouldn't use methods on the display side. Keep them for the update side - processing changes back into a store and such. Methods aren't reactive - they need to be called. You want your display to automatically reflect some underlying data, so you should use computed.
You should also avoid using v-html, because you end up with markup outside your templates, and that markup is static. It's not totally clear to me what will be in v-html, but you should try and keep markup in your template, and inject values using data, props or computed. Hope this helps!
If you want a div with some text that magically turns into an image tag, this could be a good use for <component :is>.

How to get input text value from AJAX to symfony controller

I have a problem to get my input text value in my controller.
This is my AJAX script:
$(document).ready(function() {
$('#valider').click(function () {
var searchText = $('#searchText').val();
$.ajax({
type: "POST",
url: "/firstproject/web/app_dev.php/parc/searchmodel/"+searchText,
data:{'type':searchText},
success: function (response) {
console.log(response);
},
error: function (response,xhr,status) {
alert("erroe"+status);
}
});
});
});
This is my view.twig where I have a text input:
{% block javascripts %}
<script src="{{ asset('bundles/js/jquery.min.js') }}"></script>
<script src="{{ asset('bundles/js/script.js') }}"></script>
{% endblock %}
<input type="text" id="searchText" name="searchText" value=" "placeholder="search by libel">
<input id="valider" type="submit" value="valider">
<h1>La liste des modeles</h1>
<table border="1">
<tr>
<th>Id</th>
<th>Libelle</th>
<th>pays</th>
<th>modifier</th>
<th>supprimer</th>
</tr>
{% for m in mod %}
<tr>
<td>{{ m.id }}</td>
<td>{{ m.libelle}}</td>
<td>{{ m.pays }}</td>
<td>
modifier
</td>
<td>supprimer</td>
</tr>
{% endfor %}
</table>
This is my controller action:
public function searchAction(Request $request){
$request->request->get('type');
dump($request);
$em = $this->getDoctrine()->getManager();
$modele = $em->getRepository("EspritParcBundle:Modele")
->searchbyLib($request);
return $this->render("EspritParcBundle:Modele:searchmodel.html.twig",array('mod'=>$modele));
}
This is my custom function searchbylib:
class ModeleRepository extends EntityRepository
{
public function searchbyLib($libele)
{
$em = $this->getEntityManager()
->createQuery('SELECT m FROM EspritParcBundle:Modele m
WHERE m.libelle LIKE :libele')
->setParameter('libele',$libele);
dump($em->getResult());
return $em->getResult();
}
}
And finally, my routing file:
searchmodel:
path: /searchmodel/{type}
defaults: { _controller: EspritParcBundle:Modele:search}
This is my output:
When entering "BMW" in the text field then click on the validation button, I would like it to show me only BMW models and the url to be redirected.
view.html.twig
{% block javascripts %}
<script src="{{ asset('bundles/js/jquery.min.js') }}"></script>
<script src="{{ asset('bundles/js/script.js') }}"></script>
{% endblock %}
<form action="{{ path('searchmodel') }}" method="POST">
<input type="text" id="searchText" name="searchText" value=" "placeholder="search by libel">
<input id="valider" type="submit" value="valider">
</form>
<h1>La liste des modeles</h1>
<table border="1">
<tr>
<th>Id</th>
<th>Libelle</th>
<th>pays</th>
<th>modifier</th>
<th>supprimer</th>
</tr>
{% for m in mod %}
<tr>
<td>{{ m.id }}</td>
<td>{{ m.libelle}}</td>
<td>{{ m.pays }}</td>
<td>
modifier
</td>
<td>supprimer</td>
</tr>
{% endfor %}
</table>
routing file:
searchmodel:
path: /searchmodel
defaults: { _controller: EspritParcBundle:Modele:search}
controller :
public function searchAction(Request $request){
$request = $request->get('type');
$em = $this->getDoctrine()->getManager();
$modele = $em->getRepository("EspritParcBundle:Modele")
->searchbyLib($request);
return $this->render("path:to:view.html.twig",array('mod'=>$modele));
}
The $type parameter is passed through the query string
searchmodel:
path: /searchmodel/{type}
defaults: { _controller: EspritParcBundle:Modele:search}
So you can directly add it to the parameter of the method like this :
public function searchAction(Request $request, $type)
{
$em = $this->getDoctrine()->getManager();
$modele = $em->getRepository("EspritParcBundle:Modele")
->searchbyLib($request);
return $this->render("path:to:view.html.twig",array('mod'=>$modele));
}
Is that help you?
I found out that in my controller $request = $request->get('type'); always return null, so I've tried with $lib = $request->getContent(); and then I did dump($lib); to display what it contains and here is the output:
So after that, I used substr function to extract only the text value and delete the rest and everything is working well.

Django form in every row of a table

I want to have a simple text form on every row of a table.
Fiddle illustration of expected result: https://jsfiddle.net/wstg759f/1/
My Models.py:
class Person(models.Model):
name = models.CharField(max_length=30)
class Quality(models.Model):
name = models.CharField(max_length=30)
person=models.ForeignKey(Person)
I have a queryset that returns aggregated list of all persons, count of qualities for each person, one random quality of this person:
[
{'the_count': 5, u'randomquality': u'Nice’, u'person__name': u'Joe'},
{'the_count': 4, u'randomquality': u'Generous’,u'person__name': u'Mike'},
{'the_count': 4, u'randomquality': u'Healthy’,u'person__name': u'John’'},
..
]
My view.html (qualities is my queryset)
<table>
<thead>
<tr>
<th>Person</th>
<th>Qualities count</th>
<th>One random quality</th>
<th>Add a Quality?</th>
</tr>
</thead>
<tbody>
{%for obj in qualities%}
<tr>
<td>{{ obj.person__name }}</td>
<td>{{ obj.the_count }}</td>
<td>{{ obj.randomquality }}</td>
<td>text form to submit a quality for this person</td>
</tr>
{% endfor %}
</tbody>
</table>
The user should be able to input a quality in the text field, and once submitted it will be added to the model, and the text field is replaced by "thanks, submitted"
The submit form have to be independent.
I have no clear direction where to look at.
How would you do?
From my reading, I understand that formset could be a solution, but they are really unclear for me.
Should I even use django form in this case?
If yes, I believe the form should take an argument form the template: I don't need the user to tell me about the person name as it's already here.
Let me know if I can clarify.
Thanks in advance.
As a bonus, maybe for later, I want to avoid page refresh.
Is ajax the only way?
You can do this with ajax, form and views
template.html
<table>
<thead>
<tr>
<th>Person</th>
<th>Qualities count</th>
<th>One random quality</th>
<th>Add a Quality?</th>
<th>Button</th>
</tr>
</thead>
<tbody>
{% for obj in qualities %}
<tr id="row_{{ obj.id }}">
<td>{{ obj.person__name }}</td>
<td>{{ obj.the_count }}</td>
<td>{{ obj.randomquality }}</td>
<td>{{ form.quality }}</td>
<td><button value="{{ obj.id }}" onclick="addQuality(this.value)">Add</button></td>
</tr>
{% endfor %}
</tbody>
</table>
<script>
function addQuality(id_object) {
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value
let data_to_backend = new FormData()
let qualityToAdd = document.getElementById(`id_${id_object}-quality`).value
if (qualityToAdd !== '') {
data_to_backend.append('quality', qualityToAdd)
data_to_backend.append('object_index', id_object)
} else return
const request = new Request("./",
{
method: 'POST',
headers: {'X-CSRFToken': csrftoken},
body: data_to_backend
})
fetch(request, {
method: 'POST',
mode: 'same-origin'
}).then(
function(response) {
if (response.status === 200) {
let tableRow = document.getElementById(`row_${ id_object }`)
tableRow.innerHTML = "<p>thanks, submitted</p>"
} else {
alert("Error")
console.log(response)
}
}
)
}
</script>
Set your views to receive a post request or just create a new urls path and another views
views.py
def addQuantity(request, codigo_orcamento):
if request.method == "POST":
form = formAddQuantity(request.POST)
if form.is_valid():
id_object = form.cleaned_data['object_index']
quality = form.cleaned_data['quality']
# get the object and add this quality
return HttpResponse(status=200)
else:
return HttpResponse(status=400)
else:
return HttpResponse(status=405)
In this view we simply check if the form is valid, get the object from db and add the quality on it
forms.py
class formAddQuantity(forms.Form):
object_index = forms.IntegerField(min_value=0)
quality = forms.CharField(max_length=100)
A simple check, but i recommend you to add more requirements to this fields
(Not tested, if throws a error let me know)

Resources