Remove elements before ajax execution - javascript

I have an html page with hidden template containers which is used by JavaScript to add new sections to the html page.
These containers/sections contains input fields that I wish to send via ajax to a php server.
I wish to remove the template containers from the html page before sending the input fields with ajax since I do not want the data from the template containers.
When I try removing the template containers from the html page before the ajax execution, it seems like JavaScript cannot find the data anymore.
I have a workaround but I'm trying to understand why this is happening.
function submitData(){
let templates = document.getElementById("template-container");
templates.remove();
let data = getData();
let dataHTMLJsonString = JSON.stringify(data);
let doIt = true;
if (doIt){
$.ajax({
type: "POST",
url: "processes/writefile.php",
data: {dataHTML: dataHTMLJsonString},
cache: false,
success: function(){
alert("5x15 Sent");
document.body.appendChild(templates);
}
});
}
The HTML
<!-- Real data -->
<div class="customer-input-container">
<label>Customers</label>
<select name="customers" class="customer-input" bold="true">
<option>1</option><option>2</option><option>3</option>
</select>
</div>
<!-- Template data -->
<div class="customer-input-container" id="template-container">
<label>Customers</label>
<select name="customers" class="customer-input" bold="true">
<option>1</option><option>2</option><option>3</option>
</select>
</div>
The JavaScript
function getData{
tmpData = "";
sectionData = document.getElementsByClassName("customer-input");
for(i = 0; i <= section.length; i++){
tmpData += sectionData[i].value;
}
}

getData() uses the DOM to get the informations. So you are getting a reference to the template DOM element, then you remove it from the DOM and now the data is not there anymore..
let templates = document.getElementById("template-container");
templates.remove();
let data = getData();
let dataHTMLJsonString = JSON.stringify(data);
I would rewrite it to something like this:
let templates = document.getElementById("template-container");
let data = getDataFromTemplates(templates); // explicits the dependency on the DOM
let dataHTMLJsonString = JSON.stringify(data);
templates.remove();
And inside getData you could use templates.getElementsByClassName("customer-input")

Related

Data update without page reload jinja2

The data has to be refreshed without page reload. Originally data is appeared on html with jinja2.
#app.route('/personal_account', methods=['POST'])
def welcome():
login = request.form['login']
data = get_default_user_data(login)
# ... processing
return render_sidebar_template("personal_account.html", data=data)
According to these data graph is building with chartist.js.
personal_account.html
<div id="data">
<ul id="consumed_values">
{% set count = 0 %}
{% for i in data.consumed_values %}
<li>{{ data.consumed_values[count] }}</li>
{% set count = count + 1 %}
{% endfor %}
</ul>
</div>
<canvas width="800" height="600" id="canvas"></canvas>
<button id="button">Update</button>
I need to update data. I am using ajax.
The function "request" make a post request to the server to the function get_selected_values in Python.
This function gives new data. But new data doesn't display in jinja2 on page. The data is still old.
personal_account.js
window.onload = draw();
function draw() {
var consumed_values = document.querySelectorAll('ul#consumed_values li');
var values = new Array();
for (var i = 0; i < consumed_values.length; i++) {
console.log(consumed_values[i].innerHTML);
values[i] = consumed_values[i].innerHTML;
}
var numbers = new Array();
for(var i=0; i<consumed_values.length; i++)
{
numbers[i]=i+1;
console.log(numbers[i]);
}
var ctx = document.getElementById('canvas').getContext('2d');
var grapf = {
labels : numbers,
datasets : [
{
strokeColor : "#6181B4",
data : values
}
]
}
new Chart(ctx).Line(grapf);
}
document.getElementById('button').onclick=function () {
request();
}
function reques() {
var first = selected[0];
var second = selected[1];
first.month = first.month+1;
second.month = second.month+1;
$.ajax({
type: 'POST',
url: '/get_selected_values',
success: function(response) {
alert('Ok');
draw();
},
error: function() {
alert('Error');
}
});
}
Function get_selected_values()
#app.route('/get_selected_values', methods=['POST'])
def get_selected_values():
# ...
data = fetch_selected_date(start_date=start_date, end_date=end_date, login=current_user.get_id())
if data:
# return jsonify({'result': True, 'data': data}) # does not work this way
# return jsonify({'result': False, 'data': []})
return render_sidebar_template("personal_account.html", data=data, result=1)
How to succeed in data's update and graph's rebuild?
EDIT 1
I am using the first version of get_selected_values function.
The request function look like this:
...
success: function(response) {
alert('Успешно получен ответ:!'+ response.data);
document.getElementById('consumed_values').innerHTML = response.data;
draw();
},
...
Data is updating successfully, but graph looks the same. How to fix?
OK here's my outlook on this. You're on the right track and there is a way to update the element without the need to re-draw the page in this instance. What's happening is that you are returning data from your get_selected_values() method but not doing anything with it once it's returned to your AJAX request.
So firstly, I'm going to draw your attention to your AJAX request:
$.ajax({
type: 'POST',
url: '/get_selected_values',
success: function(response) {
alert('Ok');
draw();
},
error: function() {
alert('Error');
}
});
When you're getting a successful response from this, you're seeing your "OK" alert in the UI, right? However nothing updates in the UI despite you calling on the draw() method?
You won't want to return a render_template from your Flask function in this case. You were already on the right track with returning JSON from your function:
if data:
# return jsonify({'result': True, 'data': data}) # does not work this way
When you return your JSON data, it will be stored in the response variable in your success function. If you're unsure of exactly what's going into that response variable then output its contents with something like alert(JSON.stringify(response)) in the success function of your AJAX request. From here you will see your data returned to your method.
Now you need to decide how you want to use that data to update your <div id="data"> element in your UI. You can do this just using JavaScript with a series of document.getElementById('element_id').innerHTML statements or such-like so that your element is populated with all of the updated data from your response.
This will auto-update the data you wish to have displayed without the need to refresh the page.
Now that you've done that, invoke your draw() function again and it should now use the updated data.
I hope this helps set you down the right path with this one!
AFTER EDIT 1
When you're originally populating <div id="data"> you are using a loop to populate a series of <li> tags in the element with your data.
When you are updating this element with your new data, you are just using .innerHTML to re-populate the parent <ul> element.
Your draw() method is looking to the data stored in the <li> elements.
Are you absolutely certain that, after you perform your update, your <div id="data"> element is in exactly the same (ie. expected) format to work with your draw() method? In that it's still in the structure:
<div id="data">
<ul id="consumed_values">
<li>Your updated data here...</li>
<li>More updated data...</li>
</ul>
</div>
This is the element structure that your draw() method is expecting to find. It's pulling its data in from each individual <li> element in the list. So these are the elements which need to store your updated values.

How do I populate a list field in a model from javascript?

I have a Kendo.MVC project. The view has a model with a field of type List<>. I want to populate the List from a Javascript function. I've tried several ways, but can't get it working. Can someone explain what I'm doing wrong?
So here is my model:
public class Dashboard
{
public List<Note> ListNotes { get; set; }
}
I use the ListNotes on the view like this:
foreach (Note note in Model.ListNotes)
{
#Html.Raw(note.NoteText)
}
This works if I populate Model.ListNotes in the controller when the view starts...
public ActionResult DashBoard(string xsr, string vst)
{
var notes = rep.GetNotesByCompanyID(user.ResID, 7, 7);
List<Koorsen.Models.Note> listNotes = new List<Koorsen.Models.Note>();
Dashboard employee = new Dashboard
{
ResID = intUser,
Type = intType,
FirstName = user.FirstName,
LastName = user.LastName,
ListNotes = listNotes
};
return View(employee);
}
... but I need to populate ListNotes in a Javascript after a user action.
Here is my javascript to make an ajax call to populate ListNotes:
function getReminders(e)
{
var userID = '#ViewBag.CurrUser';
$.ajax({
url: "/api/WoApi/GetReminders/" + userID,
dataType: "json",
type: "GET",
success: function (notes)
{
// Need to assign notes to Model.ListNotes here
}
});
}
Here's the method it calls with the ajax call. I've confirmed ListNotes does have the values I want; it is not empty.
public List<Koorsen.Models.Note> GetReminders(int id)
{
var notes = rep.GetNotesByCompanyID(id, 7, 7);
List<Koorsen.Models.Note> listNotes = new List<Koorsen.Models.Note>();
foreach (Koorsen.OpenAccess.Note note in notes)
{
Koorsen.Models.Note newNote = new Koorsen.Models.Note()
{
NoteID = note.NoteID,
CompanyID = note.CompanyID,
LocationID = note.LocationID,
NoteText = note.NoteText,
NoteType = note.NoteType,
InternalNote = note.InternalNote,
NoteDate = note.NoteDate,
Active = note.Active,
AddBy = note.AddBy,
AddDate = note.AddDate,
ModBy = note.ModBy,
ModDate = note.ModDate
};
listNotes.Add(newNote);
}
return listNotes;
}
If ListNotes was a string, I would have added a hidden field and populated it in Javascript. But that didn't work for ListNotes. I didn't get an error, but the text on the screen didn't change.
#Html.HiddenFor(x => x.ListNotes)
...
...
$("#ListNotes").val(notes);
I also tried
#Model.ListNotes = notes; // This threw an unterminated template literal error
document.getElementById('ListNotes').value = notes;
I've even tried refreshing the page after assigning the value:
window.location.reload();
and refreshing the panel bar the code is in
var panelBar = $("#IntroPanelBar").data("kendoPanelBar");
panelBar.reload();
Can someone explain how to get this to work?
I don't know if this will cloud the issue, but the reason I need to populate the model in javascript with an ajax call is because Model.ListNotes is being used in a Kendo Panel Bar control and I don't want Model.ListNotes to have a value until the user expands the panel bar.
Here's the code for the panel bar:
#{
#(Html.Kendo().PanelBar().Name("IntroPanelBar")
.Items(items =>
{
items
.Add()
.Text("View Important Notes and Messages")
.Expanded(false)
.Content(
#<text>
#RenderReminders()
</text>
);
}
)
.Events(e => e
.Expand("getReminders")
)
)
}
Here's the helper than renders the contents:
#helper RenderReminders()
{
if (Model.ListNotes.Count <= 0)
{
#Html.Raw("No Current Messages");
}
else
{
foreach (Note note in Model.ListNotes)
{
#Html.Raw(note.NoteText)
<br />
}
}
}
The panel bar and the helpers work fine if I populate Model.ListNotes in the controller and pass Model to the view. I just can't get it to populate in the javascript after the user expands the panel bar.
Perhaps this will do it for you. I will provide a small working example I believe you can easily extend to meet your needs. I would recommend writing the html by hand instead of using the helper methods such as #html.raw since #html.raw is just a tool to generate html in the end anyways. You can write html manually accomplish what the helper methods do anyway and I think it will be easier for you in this situation. If you write the html correctly it should bind to the model correctly (which means it won't be empty on your post request model) So if you modify that html using javascript correctly, it will bind to your model correctly as well.
Take a look at some of these examples to get a better idea of what I am talking about:
http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
So to answer your question...
You could build a hidden container to hold your list values like this (make sure this container is inside the form):
<div id="ListValues" style="display:none">
</div>
Then put the results your ajax post into a javascript variable (not shown).
Then in javascript do something like this:
$('form').off('submit'); //i do this to prevent duplicate bindings depending on how this page may be rendered futuristically as a safety precaution.
$('form').on('submit', function (e) { //on submit, modify the form data to include the information you want inside of your ListNotes
var data = getAjaxResults(); //data represents your ajax results. You can acquire and format that how you'd like I will use the following as an example format for how you could save the results as JSON data: [{NoteID ="1",CompanyID ="2"}]
let listLength = data.length;
for (let i = 0; i < listLength; i++) {
$('#ListValues').append('<input type="text" name="ListNotes['+i+'].NoteID " value="' + data.NoteID +'" />')
$('#ListValues').append('<input type="text" name="ListNotes['+i+'].CompanyID " value="' + data.CompanyID +'" />')
//for your ajax results, do this for each field on the note object
}
})
That should do it! After you submit your form, it should automatically model bind to you ListNotes! You will be able to inpsect this in your debugger on your post controller action.

Create Array from HTML to send via AJAX

Im having a unusually hard time with this. If I have form that looks like this
HTML
<form id='logForm' method='post' action='seatingProcess.php'>
<span class='close' style='display:none' id='255' desk='9-4' deskval='2-3' changeType='REMOVE'></span>
<span class='close' style='display:none' id='255' desk='7-4' deskval='5-3' changeType='ADD'></span>
<span class='close' style='display:none' id='255' desk='8-4' deskval='8-3' changeType='CHANGE'></span>
<div class='btn btn-primary' type='submit' id='submit'>Submit</div>
</form>
What I want to happen is, when i click the button to submit the form, I want to have an array of the different elements in the span created so it can be sent via AJAX to process in PHP. How do you recommend I do this?
Also, this information will be dynamically created in this form based on user action. They will all be span's but will contain more or less the same attributes with a value attached to them. The idea is for php to receive the arrays and depending on what the attribute "changeType" says, it will generate the SQL script to perform that action. I may need help with this as well.
All I have for javascript. I dont have anything about making the array, thats what I need help with.The HTML above is an example output, but ill post one of the functions that generates the information. :
Javascript
function remDeskId(){
userObject = $dropObject.find('div.dragTest');
userObjectChange = 'REMOVESEAT';
userObjectID = userObject.attr('data-info');
userObjectDeskID = userObject.attr('data-id');
userObjectDeskIDVal = 0;
$('form#logForm').append("<span class='close' style='display:none' id='"+userObjectID+"' desk='"+userObjectDeskID+"' deskval='"+userObjectDeskIDVal+"' changeType='"+userObjectChange+"'></span>");
userObject.attr({"data-id":""}); //remove desk number for new user location
userObject.appendTo('#userPool');
}
$('#submit').click(function(){
// get the form data
// there are many ways to get this data using jQuery (you can use the class or id also)
//var formData = {
// };
// process the form
$.ajax({
type : 'POST', // define the type of HTTP verb we want to use (POST for our form)
url : 'seatingProcess.php', // the url where we want to POST
data : $('#logForm').serialize(), // our data object
})
// using the done promise callback
.done(function(data) {
// log data to the console so we can see
console.log(data);
// here we will handle errors and validation messages
});
// stop the form from submitting the normal way and refreshing the page
event.preventDefault();
});
Thanks in advance
You can iterate through the spans and create an array.
var spans = $('#logForm span');
var data = [];
$.each(spans, function(i, item){
var newItem = {};
newItem.id = $(item).attr('id');
newItem.desk = $(item).attr('desk');
newItem.deskval = $(item).attr('deskval');
newItem.changeType = $(item).attr('changeType');
data.push(newItem);
});

How to submit dynamically created hidden variables using Jquery

I have created a dynamic table. DEMO to my project.
I have placed this dynamic table in the form under a div named 'box'
<div id="box">
</div>.
I am creating dynamic hidden variables table using Jquery which I need to store in DB. This is how I am creating the hash to submit to server.
criteria = $('form_name').serialize(true);
criteria = Object.toJSON(criteria);
// Build the object to store the parameters for the AJAX post request
parameters = {
title : $('report_title').value,
description : $('report_description').value,
criteria : criteria
}
// Make the AJAX post request
new Ajax.Request( URL, {
method: 'post',
parameters: parameters,
onSuccess: function( response ) {
$('messageSpan').innerHTML = response.responseText;
$('spinner').style.display='none';
}
});
I am not able to capture the dynamically created values in the criteria.
How to solve this?
In the dynamically created section, I tried adding a submit button and see if the values can be fetched. I am able to fetch and iterate all the hidden variables.
$('#jquerysaveButton').click(function(){
jsonObj = [];
$("input[id=rubric_cell]").each(function () {
var id = "cell_" + row + "_" + col;
item = {}
item["id"] = id;
item["selected_rubric"] = $(this).val();
jsonObj.push(item);
});
console.log(jsonObj); //I am getting the required values here
});
How to get these values in the criteria = $('form_name').serialize(true);. Am I doing some thing wrong? Please help me. thanks in advance.
DEMO to my project
You need to make sure that your hidden input fields have a name attribute set otherwise $.serialize will not process them.

Get Django Item ID In Ajax URL

I have a select box in an item edit page, which i would like to be populated via an Ajax call with the saved values.
<script type="text/javascript">
$(document).ready(function() {
$('#editPrefabLineclassBox').on('change', function() {
var selected = this.value;
$.ajax({
url: '/edit-prefab/,
type: 'POST',
data: {
csrfmiddlewaretoken: '{{ csrf_token }}',
lineclassSelected: selected
},
success: function(data) {
var name, select, option;
select = document.getElementById('editPrefabNameBox');
select.options.length = 0;
for (name in data) {
if (data.hasOwnProperty(name)) {
select.options.add(new Option(data[name], name));
}
}
}
});
});
})
</script>
The url i am using in the call is /edit-prefab/. The problem i am having is, the url of the page in Django is actually /edit-prefab/{{ material_item.id }}, only i am not sure how to pass this id to javascript to use in the Ajax call. With just the /edit-prefab/, the page is not found.
After populating the select with the list of items, i would like to have preselected the saved values of the item being edited. I am sure i could populate everything as needed. Its just the setting up of the url that has me a little confused
I have tried passing the id of the item through the view to the template with JSON.dumps, and then parse the variable in JS to use in the url, but i keep getting an unexpected column error when parsing, as from what i know only a dict can be parsed correctly with JSON.
Is there anyone who could please help with this?
EDIT:
def editprefabitem(request, materialitem_id):
context = dict()
mat_item = MaterialItem.objects.get(id=materialitem_id)
context['itemid'] = json.dumps(mat_item.id)
context['lineclass'] = json.dumps(mat_item.lineclass)
context['itemname'] = json.dumps(mat_item.name)
context['diameter'] = json.dumps(mat_item.diameter)
context['quantity'] = json.dumps(mat_item.quantity)
if request.method == 'POST':
if 'lineclassSelected' in request.POST:
lclass = Lineclass.objects.filter(lineclassname=request.POST['lineclassSelected'])\
.values_list('itemname', flat=True).distinct()
request.session['lineclassselected'] = request.POST['lineclassSelected']
lineclass = valuesquerysettodict(lclass)
return HttpResponse(json.dumps(lineclass), content_type='application/json')
if 'itemSelected' in request.POST:
item = Lineclass.objects.filter(itemname=request.POST['itemSelected'])[0]
diams = Lineclass.objects.filter(itemname=item.itemname).values_list('dn1', flat=True).distinct()
request.session['itemselected'] = request.POST['itemSelected']
diameters = valuesquerysettodict(diams)
return HttpResponse(json.dumps(diameters), content_type='application/json')
if 'diamSelected' in request.POST:
request.session['diameterselected'] = request.POST['diamSelected']
if 'editPrefabQuantityBox' in request.POST:
code = Lineclass.objects.filter(lineclassname=request.session['lineclassselected'])\
.filter(itemname=request.session['itemselected']).filter(dn1=request.session['diameterselected'])[0]\
.code
mat_item.name = request.session['itemselected'],
mat_item.type = 'Prefabrication',
mat_item.lineclass = request.session['lineclassselected'],
mat_item.diameter = request.session['diameterselected'],
mat_item.quantity = request.POST['editPrefabQuantityBox'],
mat_item.workpack = Workpack.objects.get(id=request.session['workpackselected']),
mat_item.code = code,
mat_item.datecreated = datetime.datetime.today(),
mat_item.createdby = request.user.username
mat_item.save()
return HttpResponseRedirect('/prefabs/')
return render_to_response('editprefab.html', context, context_instance=RequestContext(request))
The context['itemid'], context['lineclass'] etc, is where i am grabbing the current values of the item and trying to send them through to the template to be parsed by javascript to set the default values for editing in the select boxes, and provide the items id in the url.
The valuesquerysettodict() function, is a small snippet i found, to convert a Models, values_list into a JSON serializable dict to populate the select based on the parameter that was sent through from Ajax. The reason i am using it, is if i return Lineclass.objects.all(), there are a lot of items in the queryset, with the same name, but different itemcode, so i am using a values_list to try and get unique item names to use with the select.
I am sure i am going wrong somewhere i am just not sure where.
thank you for any help you could give.
So I assume you're making your AJAX call at the click of a submit button. Either way, you can supply the Django variable in the value attribute of any tag and retrieve it like this.
In the value attribute of your submit button, pass the Django ID as such:
<button type="submit" value="{{ material_item.id }}" id="submit-button"></button>
Now, in your AJAX request, you can retrieve the ID and send it with your AJAX request like this:
$(document).ready(function(event){
$(document).on('click', '#submit-button' , function(event){
event.preventDefault();
var pk = $(this).attr('value');
data:{
'id': pk,
}
....
});
});

Categories