I have a m_template.html file which has a script as follow:
<script>
$("#id_country").change(function () {
var countryId = $(this).val(); // get the selected country ID from the HTML input
$.ajax({ // initialize an AJAX request
url: '/ajax/ajax_load_cities',
data: {
'countries': countryId // add the country id to the GET parameters
},
dataType: 'json',
success: function (data) { // here data comes from url output or load_cities function
$("#preview-items").html(data.tags);
}
});
});
</script>
In the same template.html I defined a section like:
<div id="preview-items">
{% for item in itemslist %}
<label class="btn btn-primary mr-1">
<input type="checkbox" id="checklist" value="{{ item.0 }}">
<span>
{{ item.1 }}
</span>
</label>
{% endfor %}
</div>
and load_cieties:
def load_cities(request):
....
data = {
'tags': list(cities)
}
return JsonResponse(data)
Where problem happens:
The problem is in the line $("#preview-items").html(data.tags); which rather than passing list, replaces list in the <div> so at the moment I have something like:
id1name1,id2name2,id3name3,...
My Question:
How to pass data.tags which is a list of tuples to section as a parameter that within which I be able to style list items as I already defined in ?
data.tags is something like [(id1, name1), (id2, name2), (id3, name3), ..]
I would use a bit more sophisticated code (like React), but would this solve the immediate issue?
First, javascript doesn't have tuples, so send it a list of lists (json) from python: [['id1', 'name1'], ['id2', 'name2'], ['id3', 'name3']];
success: function (data) {
$('#preview-items').html('');
for (var i in data) {
console.log(i, data);
$('#preview-items').append(`
<label class="btn btn-primary mr-1">
<input type="checkbox" id="checklist" value="` + data[i][0] + `">
<span>
` + data[i][1] + `
</span>
</label><br />`
);
}
}
(Note the use of backticks in the javascript multi-line string)
Related
I'm trying to make the search of 'patient' Dynamic with ajax. Every thing in my code is working well but I don't know wy request.is_ajax() always returns false. I search about it but I didn't find the solution yet, right now my code do the search but with changing of the url and that mean the js dosen't work. I don't know how work well with javascript in Django so please help me.
This is my views.py:
def index(request):
ctx = {}
url_parameter = request.GET.get("q")
if url_parameter:
queryset = Patient.objects.annotate(fullname=Concat('first_name', Value(' '), 'last_name'))
patients = queryset.filter(fullname__icontains=url_parameter)
#patients = Patient.objects.filter(name__icontains=url_parameter)
else:
patients = Patient.objects.all()
ctx["patients"] = patients
print(request.is_ajax())
if request.is_ajax():
html = render_to_string(template_name="patient/patients-results-partial.html",context={"patients": patients})
data_dict = {"html_from_view": html}
return JsonResponse(data=data_dict, safe=False)
return render(request, "patient/index.html", context=ctx)
index.html:
{% extends 'base.html' %}
{% block content %}
<div class="col-md-6 offset-md-4">
{# part added for dynamic search#}
{# icon and search-box #}
<form class="form-inline">
<i id="search-icon" class="fas fa-search" aria-hidden="true"></i>
<input id="patient-input" class="form-control form-control-sm ml-3 w-75" type="text" placeholder="Search" aria-label="Search" name="q">
</form>
{# artist-list section #}
<div id="replaceable-content" class="col-6">
{% include 'patient/patients-results-partial.html' %}
</div>
</div>
<div class="col-md-6 offset-md-4">
Ajouter un nouveau patient
</div>
<div class="col-md-6 offset-md-4">
<div class="table-responsive">
<table class="table table-striped table-sm">
<thead>
<tr>
<th>Prénom</th>
<th>Nom</th>
<th>Téléphone</th>
<th>Sexe</th>
<th>Date de naissance</th>
<th>Docteur</th>
</tr>
</thead>
<tbody>
{% for field in patients %}
<tr>
<td>{{field.first_name}}</td>
<td>{{field.last_name}}</td>
<td>{{field.phone}}</td>
<td>{{field.sex}}</td>
<td>{{field.birth_date}}</td>
<td>{{field.doctor}}</td>
<td>Details</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock content %}
and this is my js code:
const patient_input = $("#patient-input");
const search_icon = $('#search-icon');
const patients_div = $('#replaceable-content');
const endpoint = '/patient/';
const delay_by_in_ms = 700;
let scheduled_function = false;
let ajax_call = function (endpoint, request_parameters) {
$.getJSON(endpoint, request_parameters)
.done(response => {
// fade out the patients_div, then:
patients_div.fadeTo('slow', 0).promise().then(() => {
// replace the HTML contents
patients_div.html(response['html_from_view'])
// fade-in the div with new contents
patients_div.fadeTo('slow', 1)
// stop animating search icon
search_icon.removeClass('blink')
})
})
}
patient_input.on('keyup', function () {
const request_parameters = {
q: $(this).val() // value of patient_input: the HTML element with ID patient-input
}
// start animating the search icon with the CSS class
search_icon.addClass('blink')
// if scheduled_function is NOT false, cancel the execution of the function
if (scheduled_function) {
clearTimeout(scheduled_function)
}
// setTimeout returns the ID of the function to be executed
scheduled_function = setTimeout(ajax_call, delay_by_in_ms, endpoint, request_parameters)
})
I think this kind of AJAX call, is clean and easier than what you have in your code.
This model AJAX is working for me.
Maybe this js code helps you to fix your bug.
$('#form').on('submit', function (event) {
event.preventDefault();
const form = $(this);
const submit_btn = form.find('#submit-button');
$.ajax({
url: 'your URL for send ajax call',
type: 'POST', // Method of call, such as POST or GET
data: 'data as JSON', // You can use 'form.serialize()' to
beforeSend: function () {
// This line calls before that AJAX is called.
},
success: function (data) {
// If the back-end returns a JSON response with 200 status code, js will run this line.
},
error: function (data) {
// If the back-end returns a JSON response with 400 status code, js will run this line.
},
complete: function () {
// After success or error is called , this function will be called
},
})
})
My JSON file will return 2 difference values.
If record exist, JSON will return:
[{"ic":"000000000001","name":"SITI"}]
If record not exist, JSON will return:
{"error":"No Record."}
For the record exist, I managed to display the value in HTML, but why when the error value, it does not display the "No Record." in my HTML?
Javascript code:
callApi(operation, "72eafd5c6bab3fdc731f395675f7b9483729ef", "get", configObj).then(function (result) {
result.data.forEach(function (v) {
if (result.error) {
var error = v.error
$(".result").show()
$(".value.error").text(error)
} else {
var name = v.name
var ic = v.ic
$(".result").show()
$(".value.name").text(name)
$(".value.ic").text(ic)
}
})
})
HTML code:
<div class="result">
<div class="separationLine"></div>
<div class="label custom_secText">
<center>DISPLAY HERE..</center>
</div>
<span class="value error"></span>
<p>Name : <span class="value name"></span></p>
<p>IC : <span class="value ic"></span></p>
<hr />
</div>
It looks like you dont get inside the if statement. Have you debugged ii or placed a console.log inside this if statment?
Does it help if you change this part
if("error" in result) {
?
I am modifying a FormSet using JavaScript/jQuery by dynamically adding a form to a Django FormSet. For example, I start with one form asking about a User's education. The User can then press an add button to add an identical form to input information about secondary schooling (e.g. grad school). The form gets added in the browser and I can input data, but when I POST the data, it only shows one form in the FormSet with the information from the second form in the browser.
POST DATA
edu-0-degree u'Doctorate'
first_name u'User'
last_name u'One'
Submit u'Submit'
edu-0-date_started u'01/01/12'
edu-MIN_NUM_FORMS u'0'
edu-0-school u'School Two'
edu-INITIAL_FORMS u'0'
edu-MAX_NUM_FORMS u'1000'
edu-0-date_finished u'01/01/16'
edu-0-id u''
edu-TOTAL_FORMS u'2'
csrfmiddlewaretoken u'qgD2supjYURWoKArWOmkiVRoBPF6Shw0'
I'm then getting an error saying:
ValidationError: [u'ManagementForm data is missing or has been tampered with'].
Here are the relevant pieces of code:
views.py
def build_profile(request):
EducationFormset = modelformset_factory(EducationModel, AddEducationForm, extra=1)
if request.method == "POST":
education_formset = EducationFormset(request.POST, prefix='edu')
for form in education_formset:
if form.is_valid() and form.has_changed():
education = EducationModel(
school = form.cleaned_data['school'],
date_started = form.cleaned_data['date_started'],
date_finished = form.cleaned_data['date_finished'],
degree = form.cleaned_data['degree'],
user = current_user
)
education.save()
return HttpResponseRedirect(reverse('private', args=[current_user.username]))
context = {
'edu_formset' : forms['education'],
}
return render(request, "build_profile.html", context)
(Here I've tried with and without the form.has_changed() piece with the same result.)
Template build_profile.html
<h2>Education</h2>
{{ edu_formset.management_form }}
{% for form in edu_formset.forms %}
<div id="{{ form.prefix }}-row" class="dynamic-form">
{{ form|crispy }}
<div {% if forloop.first %} class="hidden" {% endif %}>
<button type="button" class="btn btn-default btn-sm delete-row">
<span class="glyphicon glyphicon-minus" aria-hidden="true"></span>
</button>
</div>
</div>
{% endfor %}
<div class="btn-group btn-group-xs" role="group" aria-label="...">
<button type="button" class="btn btn-default add-row">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
</button>
</div>
build_profile.js (The code to dynamically add forms to the FormSet)
function updateElementIndex(el, prefix, ndx) {
var id_regex = new RegExp('(' + prefix + '-\\d+)');
var replacement = prefix + '-' + ndx;
if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
if (el.id) el.id = el.id.replace(id_regex, replacement);
if (el.name) el.name = el.name.replace(id_regex, replacement);
}
function addForm(btn, prefix) {
var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
var row = $('.dynamic-form:first').clone(true).get(0);
$(row).removeAttr('id').insertAfter($('.dynamic-form:last')).children('.hidden').removeClass('hidden');
$(row).children().not(':last').children().each(function() {
updateElementIndex(this, prefix, formCount);
$(this).val('');
});
$(row).find('.delete-row').click(function() {
deleteForm(this, prefix);
});
$('#id_' + prefix + '-TOTAL_FORMS').val(formCount + 1);
return false;
}
function deleteForm(btn, prefix) {
$(btn).parents('.dynamic-form').remove();
var forms = $('.dynamic-form');
$('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
for (var i=0, formCount=forms.length; i<formCount; i++) {
$(forms.get(i)).children().not(':last').children().each(function() {
updateElementIndex(this, prefix, i);
});
}
return false;
}
$(document).ready( function () {
$('.add-row').click( function () {
return addForm(this, 'edu')
});
$('.delete-row').click( function () {
return deleteForm(this, 'edu')
});
});
What am I doing wrong?
You're getting the ValidationError because edu_TOTAL-FORMS = 2 and only 1 form from the formset is in your post args. View source in the browser and make sure that the names of your forms are prefixed properly. It looks like both forms have the edu-0 prefix and when you submit only the last one on the form is posted.
I want to append HTML/data to div when the checkboxes is checked. I also want to know the best practices to how append data/html easily from the checkboxes.
However, please see the code below:
Ajax
$('.myCheck').on('ifChecked', function (event) {
$.ajax({
url: '/Home/getCategoryItems',
type: "GET",
cache: false,
data: {
name: $(this).attr("name")
},
success: function (data) {
setTimeout(function () {
}, 3000);
}
});
});
View:
#foreach (var item in Model.Cars)
{
<span class="label">
#item.CategoryName <span class="badge">#item.CategoryCount</span>
</span>
#Html.CheckBox(item.CategoryName, new { #class = "myCheck", })
#Html.Hidden("name", item.CategoryName, new { id = item.CategoryId })
}
Controller:
[HttpGet]
public JsonResult getCategoryItems(string name)
{
var select = (from r in _db.Cars
where r.Category.Name == name
select new
{
r.Title,
r.Price,
r.FileName,
r.Category.Name,
r.City,
r.TagName,
r.Id,
}).ToList();
return new JsonResult { Data = select, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
This is what I want to append:
#foreach (var item in Model)
{
<div class="container" id="sek1">
<div class="row">
<div class="col-md-12 no-padding-lr sear-result-column">
<div class="latest-job article-row1">
<div class="col-md-2 no-padding-lr resp-grid1 box-sadow">
<img src="https://wp-themes.com/wp-content/themes/jobile/images/no-image.jpg" width="100" height="86">
</div>
<div class="col-md-10 no-padding-lr">
<div class="col-md-8 col-sm-8 col-xs-8 no-padding-lr job-status resp-grid1 job-status-3">
<h3>#item.Title</h3>
</div>
<div class="col-md-4 col-sm-4 col-xs-4 job-status resp-grid1 job-status-3">
<a class="btn btn-primary" id="LesMerBtn">#item.Price</a>
</div>
<div class="col-md-12 no-padding-lr">
<div class="job-btn-group late-job-btn clearfix">
<span class="glyphicon glyphicon-map-marker"></span>#item.City
<span class="glyphicon glyphicon-list-alt"></span>Kategori: #item.CategoryName
</div>
</div>
<div class="col-md-12 no-padding-lr">
<p class="result-btm-text"></p><p>Test....</p>
<span class="glyphicon glyphicon-eye-open" id="eye-open"></span>Read more<p></p>
</div>
</div>
</div>
</div>
</div>
</div>
}
You will get the json response in your success event of your ajax call. The response is of an array and you need to iterate through the array and get each item in the array, read the property values and use that to build your html markup you want to append.
success: function (data) {
var myHtml="";
$.each(data,function(a,b){
myHtml+="<div><p>"+b.Title+"</p>";
myHtml+="<p>"+b.City+"</p>";
myHtml+="<p>"+b.Price+"</p></div>";
});
$("#YourDivId").append(myHtml);
}
Assuming YourDivId is the Id of the Div where you want to show the data coming from your ajax call and this div exists in your page.
This works if you are making simple html markup. But if you have some complicated markup you want to appen/show. i recommend returning a partial view from your ajax call.
So in your action method, instead of returning the json data, pass that data to your partial view and let the action method returns the razor generated html markup with the data.
Assuming you have a view model like this to represent a Car
public class CarVm
{
public string Title { set;get;}
public decimal Amount { set;get;}
public string City { set;get;}
}
In your action method, create a list of CarVm from the data from your db table and pass that to the partial view.
[HttpGet]
public JsonResult getCategoryItems(string name)
{
var carVmList= (from r in _db.Cars
where r.Category.Name == name
select new CarVm { Title =r.Title,
City =r.City,
Price=r.Price
}
).ToList();
return PartiaView("CarsPerCategory",carVmList);
}
Assuming you have a partial view called CarsPerCategory.cshtml which is strongly typed to a collection of CarVm type. The partial view should exist in either ~/Views/Shared/ or ~/Views/YourCurrentControllerName/
#model List<CarVm>
#foreach (var item in Model)
{
<p>#item.Title</p>
<!-- Add the remaining markup you want (same as the code in your question) -->
}
And in your success event you simply append the response coming back to your container div.
success: function (data) {
$("#YourDivId").append(data);
}
you may use append() method or html() method depending on you want to replace the existing value or just append it.
I'm trying to make a list of items (telephones and dependents for a customer), for example, the user could include some number phones and remove others (maybe edit them if it is possible), like a list inside the record of customer.
I'd like to know how can I do it on client side and get the list in server side ?
Is there a jquery plugin or a best pratice to do it?
P.S.: I'm using ASP.Net MVC 2.
Serialise the data into a format like JSON and then send it to the server as a string.
When I had to learn it, these posts were extremely useful.
http://encosia.com/2008/05/29/using-jquery-to-directly-call-aspnet-ajax-page-methods/
http://encosia.com/2008/03/27/using-jquery-to-consume-aspnet-json-web-services/
You can serialise a javascript array into a string that ASP.Net can deserialise.
There is a standard called JSON which is good, as it adds nearly no noise on the actual data (like xml does, incrementing a LOT the amount of data to transfer).
You can then use the $.ajax jquery method to send this data to a WebMethod you created (see links) and get an understandable response back.
EDIT:
If you were already inside this stuff, you can simply use the JSON.stringify() method, passing the object/array to serialise in it.
I keep this example around to get me started, just put the proper stuff in the proper files and edit it to match what you are doing:
/* in this case I am using */
available at: http://www.json.org/js.html
function jsonObject()
{
};
var phoneListObject = new jsonObject();
function SaveJsonObject()
{
phoneListObject.Control = new jsonObject();
phoneListObject.Control.CustomerId = $("#CustomerId").val();
phoneListObject.Control.CustomerName = $("#CustomerName").val();
phoneListObject.ListBody.PhonesBlock = new jsonObject();
phoneListObject.ListBody.PhonesBlock.Phone = new Array();
$('#PhonesBlock .Phone').each(function(myindex)
{
phoneListObject.ListBody.PhonesBlock.Phone[myindex].PhoneNumber = $(".PhoneNumber input", this).val();
phoneListObject.ListBody.PhonesBlock.Phone[myindex].PhoneName = $(".PhoneName input", this).val();
});
};
$(function()
{
function SaveCurrentList()
{
SaveJsonObject();
var currentSet = phoneListObject;
var formData = { FormData: currentSet };
phoneListJSON = JSON.stringify(formData);
var FormData = "{ FormData:" + JSON.stringify(phoneListJSON) + "}";
SavePhoneListData(FormData);
};
function SavePhoneListData(phonesData)
{
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
data: phonesData,
dataFilter: function(data)
{
var msg;
if ((typeof (JSON) !== 'undefined') &&
(typeof (JSON.parse) === 'function'))
msg = JSON.parse(data);
else
msg = eval('(' + data + ')');
if (msg.hasOwnProperty('d'))
return msg.d;
else
return msg;
},
url: "../../WebServices/ManagePhones.asmx/SaveJson",
success: function(msg)
{
SaveSuccess(msg);
},
complete: function(xhr, textresponse)
{
var err = eval("(" + xhr.responseText + ")");
},
error: function(msg)
{
},
failure: function(msg)
{
}
});
};
$('#btnSave').click(function()
{
SaveCurrentList();
});
});
/* json data snip */
{"FormData":{"Control":{"CustomerId":"12345y6","CustomerName":"Joe Customer"},"PhonesBlock":{"Phone":[{"PhoneNumber":"234-233-2322","PhoneName":"son harry"},{"PhoneNumber":"234-233-2323","PhoneName":"son frank"},{"PhoneNumber":"234-233-2320","PhoneName":"momk"}]}}}
/XML of the form data:/
<FormData>
<Control>
<CustomerId>12345y6</CustomerId>
<CustomerName>Joe Customer</CustomerName>
</Control>
<PhonesBlock>
<Phone>
<PhoneNumber>234-233-2322</PhoneNumber>
<PhoneName>son harry</PhoneName>
</Phone>
<Phone>
<PhoneNumber>234-233-2323</PhoneNumber>
<PhoneName>son frank</PhoneName>
</Phone>
<Phone>
<PhoneNumber>234-233-2321</PhoneNumber>
<PhoneName>momk</PhoneName>
</Phone>
</PhonesBlock>
</FormData>
/* form layout snip */
<div class="control">
<div class="customer">
<input typeof="text" id="CutomerId" />
<input typeof="text" id="CutomerName" />
</div>
<div class="phoneslist" id="PhonesBlock">
<div class="Phone">
<input typeof="text" class="PhoneNumber" />
<input typeof="text" class="PhoneName" />
</div>
<div class="Phone">
<input typeof="text" class="PhoneNumber" />
<input typeof="text" class="PhoneName" />
</div>
<div class="Phone">
<input typeof="text" class="PhoneNumber" />
<input typeof="text" class="PhoneName" />
</div>
</div>
</div>
<input id="buttonSave" class="myButton" type="button" value="Save" />
signature of the web service method:
[WebMethod(EnableSession = true)]
public string SaveJson(string FormData)
{
}