How do I add .each results to a <ul>? - javascript

I'm iterating through a SharePoint list and the results are passed by in JSON. This is done with .each
Then I'm using an if statement (if a certain column of data equals a certain phrase) add that result to an unordered list on the page.
My issue is it's only adding the last iteration. How can I make sure it's adding every item that matches my if statement?
$.ajax({
url: "http://site/subsite/project/_api/Web/Lists/getByTitle('SharePoint List')/items",
type: "GET",
headers: { "ACCEPT": "application/json;odata=verbose" },
success: function(data){
$.each(data.d.results, function(index) {
var courseName = $(this).attr('Title');
var courseNumber = $(this).attr('Course_x0020_Number');
var active = $(this).attr('Active');
var courseUrl = $(this).attr('URL');
var trainingGroup = $(this).attr('Training_x0020_Group');
if (trainingGroup == 'Lab') {
document.getElementById('labListSpan').innerHTML = '<ul class="courseLists"><li><input type="checkbox" id="'+courseName.replace(/\s+/g, '')+'"/>'+courseName+'</li></ul>';
}
});
},
error: function(){
alert("Failed to query SharePoint list data. Please refresh (F5).");
}
});
}
pullTrainingCourses();

document.getElementById('labListSpan').innerHTML = '<ul class="courseLists"><li><input type="checkbox" id="'+courseName.replace(/\s+/g, '')+'"/>'+courseName+'</li></ul>';
You are replacing the innerHTML every time. Instead of '=' use '+='

Related

Ajax success function to fire another ajax function whilst iterating through loop

I have the following js/jquery code:
var trigger = $('#loadTableData');
var wrapperClass = 'tableAccordionWrapper';
var url = 'data/tableData.json';
var template = 'includes/tableInput.html';
var parentWrapper = $('#selectedTables .sub-content .input-controls');
var href;
var intID;
var items;
var i;
// retrieve node data send from exteral source
addExternalTableInput = function(){
$('.tableAccordionWrapper').remove();
$.ajax({
type: 'GET',
url: url,
dataType: 'json',
success:function(data){
items = data.items
for(i in items){ // this loops 3 times
addExternalTemplate();
}
},
error:function(status){
console.log(status, "Something went wrong");
},
complete:function(){
}
});
}
// append table input to document
addExternalTemplate = function(){
var wrapper;
$.ajax({
type: 'GET',
url: template,
dataType: 'html',
success:function(data){
intID = i;
wrapper = $('<li/>');
wrapper.addClass(wrapperClass);
wrapper.attr('data-id','table-' +intID);
href = $('<a href="#"/>');
wrapper.append(href);
wrapper.append(data).insertBefore(parentWrapper);
var anchor = wrapper.find('> a');
anchor.html(items[intID].tableName); // this returns 'DB_SOURCE_3' for all 3 templates added to the DOM
},
error:function(status){
console.log(status, "Something went wrong");
},
complete:function(){
}
});
}
The concept is that I am using a small json file to run another ajax request. The length of the data in the json file determines how many times the consecutive function should be fired.
The json contains very basic data, but as I loop through it I want the second ajax function to append a template of html to the document (at which point I want to be able to run other functions). One part of data from the json file needs to be injected into the template as it is iterating through the loop.
It appears that the loop works in that in this example the html template gets appended to the dom 3 times, but it passes the last table name in the json to each template that is added to the dom. The second function appears to run after the loop has finished.
Example JSON:
{
"items":[
{
"tableName": "DB_SOURCE_1",
"tableID" : "14739",
"tableDescription" : "Main customer table"
},
{
"tableName": "DB_SOURCE_2",
"tableID" : "184889",
"tableDescription" : "Partitions table"
},
{
"tableName": "DB_SOURCE_3",
"tableID" : "9441093",
"tableDescription" : "Loans Table"
}
]
}
I have tried passing the function in the ajax complete function.
I have also tried to trigger the second ajax function inside the first ajax success function like so:
addExternalTableInput = function(){
$('.tableAccordionWrapper').remove();
$.ajax({
type: 'GET',
url: url,
dataType: 'json',
success:function(data){
items = data.items
for(i in items){
$.ajax({
type: 'GET',
url: template,
dataType: 'html',
success:function(data){
intID = i;
wrapper = $('<li/>');
wrapper.addClass(wrapperClass);
wrapper.attr('data-id','table-' +intID);
href = $('<a href="#"/>');
wrapper.append(href);
wrapper.append(data).insertBefore(parentWrapper);
var anchor = wrapper.find('> a');
anchor.html(items[intID].tableName);
},
error:function(status){
console.log(status, "Something went wrong");
},
complete:function(){
}
});
}
},
But everything I have tried seems to return the same results.
The code has been rewritten somewhat, but here is what I am doing.
var templateData;
addExternalTableInput = function(){
$('.tableAccordionWrapper').remove();
$.ajax({
type: 'GET',
url: url,
dataType: 'json',
success:function(data){
var items = data.items;
for(var i in items){
addExternalTemplate(items[i], i); // pass parameters to this function
}
},
error:function(status){
// etc.
}
});
}
addExternalTemplate = function(item, intID){ // add parameters to our function so we can access the same data
var wrapper;
// load template data once
if(!templateData){ // only run this function if !templateData (should only run once).
$.ajax({
type: 'GET',
url: template,
dataType: 'html',
async: false, // wait until we have a response before progressing
success:function(data){
templateData = data;
},
error:function(status){
console.log(status, "Something went wrong");
}
});
}
// append templateData to the dom
if(templateData){
var href = $('<a href="#"/>');
var tableNameInput = wrapper.find('[name="tables"]');
tableNameInput.val(item.tableName);
// etc
}
// update for, id and name attributes etc.
updateInputAttributes = function(){
// do other stuff to each instance of the template
}();
}
I have moved alot of the global variables out and instead I am using function parameters.
I am only calling the html template once, but for each iteration of the loop I can run functions to update certain atrributes in that instance of the template as well as match items in the json to items in the template.

jQuery add multiple filter parameters to url

I have multiple groups of checkboxes that are used to filter search results. For example, a search for shirts would have group one as colors, which includes things like, black, blue, red and group two as sizes, which includes things like, small, medium, large. Standard stuff...
The url for this example would look like the following, after a search is made, and the filters are applied:
www.xzy.dev/search?keywords=shirt&colors=red,black&sizes=small,medium
This would return me all items that match the keyword search, with the filters of colors (red and black), and sizes (small and medium).
I have all of the backend done, but I am not very great when it comes to the front end of things...
The code below does just about what I want, except it has it's flaws for my situation which I've explained below.
<script type="text/javascript">
function GetFilters() {
console.log("rom");
$('input[type="checkbox"]').on('change', function (e) {
var data = {},
fdata = [],
loc = $('<a>', { href: window.location })[0];
$('input[type="checkbox"]').each(function (i) {
if (this.checked) {
if (!data.hasOwnProperty(this.name)) {
data[this.name] = [];
}
data[this.name].push(this.value);
}
});
// get the key
var key = Object.keys(data)[0];
// and the data
// it works to without joining
var fdata = key+"="+data[key].join(',');
// and if you wanna strip the whitespaces
// use fdata = fdata.replace(/\s/g,"");
$.ajax({
type: "POST",
url: "/ajax/get",
data: {
"_token": "{{ csrf_token() }}",
"fdata": fdata
},
success: function (response) {
$('#d2d-results').html(response);
}
});
if (history.pushState) {
history.pushState(null, null, loc.pathname + '?' + fdata);
}
});
}
window.onload = GetFilters;
</script>
The code works for the most part. When I click a checkbox, it appends to the url and the ajax request is done. Works great...
But the issues I am having with said code is that when I uncheck the last checkbox to remove the final filter, it stays in the url, and casts an error:
Uncaught TypeError: Cannot read property 'join' of undefined
at HTMLInputElement.<anonymous> (677)
at HTMLInputElement.dispatch (jquery.min.js:3)
at HTMLInputElement.q.handle (jquery.min.js:3)
Second, the code only works when I use one filter group. If I try to click a checkbox from another filter group while a selection is already made from the first, for instance if colors=red,black are already selected, things fail, and for obvious reasons, because the code doesn't seem to allow it.
How can this be modified to add multiple query groups? How can I click red and black from my colors group and small and medium from my sizes group and have the url display:
www.xzy.dev/search?keywords=shirt&colors=red,black&sizes=small,medium
But also remove the actual query if I don't want to specify colors for instance?
www.xzy.dev/search?keywords=shirt&sizes=small,medium
I think your problem is that you are always only getting only one key ( if exists if it doesn't exist then the code breaks because its undefined).
you should iterate over all the keys and in that way you are also safe if you got no keys - fdata will remain empty.
<script type="text/javascript">
function GetFilters() {
$('input[type="checkbox"]').on('change', function (e) {
var data = {},
fdata = [],
loc = $('<a>', { href: window.location })[0];
$('input[type="checkbox"]').each(function (i) {
if (this.checked) {
if (!data.hasOwnProperty(this.name)) {
data[this.name] = [];
}
data[this.name].push(this.value);
}
});
// get all keys.
var keys = Object.keys(data);
var fdata = "";
// iterate over them and create the fdata
keys.forEach(function(key,i){
if (i>0) fdata += '&'; // if its not the first key add &
fdata += key+"="+data[key].join(',');
});
$.ajax({
type: "POST",
url: "/ajax/get",
data: {
"_token": "{{ csrf_token() }}",
"fdata": fdata
},
success: function (response) {
$('#d2d-results').html(response);
}
});
if (history.pushState) {
history.pushState(null, null, loc.pathname + '?' + fdata);
}
});
}
window.onload = GetFilters;

How to remove multiple tr simultaneously in jQuery without using for loop

I can do this, simply doing it in for loop, but I need to do it without using loop.
Is there any way to make it possible?
Below I am writing some of my code:
function submitFormArchive(Status) {
var siteUrl = $("#pageurl").val();
$("#archive-loader").show();
var myCheckboxes = new Array();
$("input[type='checkbox'][name='archive[]']:checked").each(function () {
myCheckboxes.push($(this).val());});
alert(myCheckboxes);///this one i am getting dynamic ids
$.ajax({
type: 'POST',
url: siteUrl + 'Appadmins/ajaxUpdateArchive',
data: {"myCheckboxes": myCheckboxes, "status": Status},
success: function (data) {
$("#remove-id-"+myCheckboxes).slice(myCheckboxes).remove();
}
});
return false;
}
<tr class="message_box" id='remove-id-<?php echo $list->id;?>'></tr>
This one in for loop
I am posting some part of codes.
$("#remove-id-" + myCheckboxes).slice(myCheckboxes).remove();
Is there any for multiple, maybe I have written wrong in this above code.
Try the code below
$("input[type='checkbox'][name='archive[]']:checked").each(function() {
myCheckboxes.push($(this).val());
});
alert(myCheckboxes); //40,39,38 //it can be any id ,as i made it dynamic .
// construct array of IDs here
var ids = myCheckboxes.map(function(id) { return "#remove-id-" + id; });
// ["#remove-id-40", "#remove-id-39", "#remove-id-38"]
// concat all id selectors together using comma `,`
var idSelector = ids.join(",");
// "#remove-id-40,#remove-id-39,#remove-id-38"
// remove all at once.
$(idSelector).remove();
$("input[type='checkbox'][name='archive[]']:checked").each(function() {
$("#remove-id-" + $(this).val()).remove();
});

AJAX list update, get new elements and count

I have this HTML list
<ul id='usernameList'>
<li class='username'>John</li>
<li class='username'>Mark</li>
</ul>
and a form to add new names via AJAX, multiple add separated by commas. The response is a list with the names
[{name:David, newUser:yes}, {name:Sara, newUser:yes}, {name:Mark, newUser:no}]
I'm trying to insert this names sorted alphabetically in the list, like this example https://jsfiddle.net/VQu3S/7/
This is my AJAX submit
var form = $('#formUsername');
form.submit(function () {
$.ajax({
type: form.attr('method'),
url: form.attr('action'),
data: form.serialize(),
dataType: "json",
beforeSend: function () {
//
},
success: function (data) {
var listUsernames = $('#usernameList');
var numUsernames = listUsernames.children().length;
$.each(data, function(i, user) {
if(user.newUser == "yes"){
var htmlUser = "<li class='username'>" + user.name + "</li>";
var added = false;
$(".username", listUsernames).each(function(){
if ($(this).text() > user.name) {
$(htmlUser).insertBefore($(this));
added = true;
}
});
if(!added)
$(htmlUser).appendTo($(listUsernames));
}
// HERE I DO alert('numUsernames')
// I get the same number of users before sending form
// How can I update here the value of listUsernames and numUsernames?
});
}
});
return false;
});
My question is, how I can update the value of listUsernames and numUsernames after adding an item?
You just need to update numUsernames at that point.
Add this where your comments are:
numUsernames = listUsernames.children().length;
listUsernames already has the updated children, as it's a reference to the parent element.
Edit: Re: your comment below:
This should probably work:
$(".username", listUsernames).each(function(){
if ($(this).text() > user.name) {
$(htmlUser).insertBefore($(this));
added = true;
return false; // stop `.each` loop.
}
});
First you don't need a double jQuery wrapping:
$(htmlUser).appendTo($(listUsernames));
listUsernames is already a jQuery object, so try:
$(htmlUser).appendTo(listUsernames);
And after every adding, you can update the numUsernames variable with:
numUsernames = listUsernames.children().length;
but this is not necessary because you can always access listUsernames.children().length in the success handler.
I update your JSFiddle
var listUsernames = $('#usernameList');
var numUsernames = listUsernames.children().length;
var data = [{name:'David', newUser:'yes'}, {name:'Sara', newUser:'yes'}, {name:'Mark', newUser:'no'}]
$.each(data, function(i, user) {
if(user.newUser == "yes"){
var htmlUser = "<li class='username'>" + user.name + "</li>";
var added = false;
$(".ingredient", listUsernames).each(function(){
if ($(this).text() > user.name) {
$(htmlUser).insertBefore($(this));
added = true;
}
});
if(!added)
$(htmlUser).appendTo($(listUsernames));
}
// HERE I DO alert('numUsernames')
// I get the same number of users before sending form
// How can I update here the value of listUsernames and numUsernames?
});

Javascript / JQuery loop through posted ajax data string to assign new values to

I have a function which updates a database via ajax. My issue is then how to update the data displayed on the page to show updated details. The POST data can vary and therefore the datastring would be something like this:
var dataString = '[name resource we are editing]=1' +
'&para1='+ para1 +
'&para2=' + para2+
'&para3=' + para3
I want the function below to split or loop through each of the POST variables in the datastring to update the text of an element on the page. I cannot figure out how.
function editAccount(dataString, details, form){
status = $(".status");
$.ajax({
type: "POST",
url: "<?php echo BASE_PATH; ?>/edit/",
data: dataString,
success: function(response) {
$.each(response, function(key, value) {
success_code = key;
message = value;
});
if(success_code == 1){
status.text(message).addClass("valid");
//show details and hide form
$("#" + details).show();
$("#" + form).hide();
//HOW to do below?
//update details being displayed with datasource data
//loop through dataString to assign eg. $('#para1')text(para1);
} else {
status.text(message).addClass("invalid");
}
},
error: function(response){
status.text("There was a problem updating your details into our database. Please contact us to report this error.").addClass("invalid");
}
});
}
As mentioned in a previous comment, I would suggest declaring the dataString variable as an object:
var dataString = { '[name resource we are editing]' : 1,
'para1': para1,
'para2': para2,
'para3': para3
}
Now it'll be much easier to loop over the params, just using the function each, for instance, which you already use in your code:
$.each(dataString, function(key, value) {
// Do stuff with each param
});
EDIT:
As #Qpirate suggests, you also can use the javascript for loop:
for(var key in dataString){
// value => dataString[key]
}

Categories

Resources