dynamically creating text boxes after loop through javascript object - javascript

I have a javascript that sends some info to through an ajax request to the server and receives some data as Questions and their's ID's as a json array.
This is what the response json array i receive from the server looks like:
[
{
"ID":"1",
"question":"Write a function called addNum. "
},
{
"ID":"3",
"question":"Write a function called sumDouble "
}
]
And this is javascript:
$(document).ready(function(){
$("form#input_qnumber").submit(function() {
var questions = $('#questions').attr('value'); // written question
var quizname = $('#quizname').attr('value');
if (questions) { // values are not empty
$.ajax({
type: "POST",
url: "https://xxxx",
contentType: "application/x-www-form-urlencoded; charset=utf-8",
dataType: "application/json",
data: 'questions='+questions+'&quizname='+quizname,
success: function (data)
{
var JSONObject = JSON.parse(data);
for (var key in JSONObject) {
if (JSONObject.hasOwnProperty(key)) {
console.log(JSONObject[key]["ID"] + ", " + JSONObject[key]["question"]);
}
}
}
});
}
else {
$('div#createquizresp').text("Enter question ID's separated by a comma to be included in the quiz");
$('div#createquizresp').addClass("error");
} // else
$('div#createquizresp').fadeIn();
return false;
});
});
As you see, I can parse the response json into a javascript object array, loop through it and dump the contents in console. What I would like though would be to create textarea element, give its id attribute the 'ID' key from my array and label it with the corresponding question key from the array. After this I can just append the element to a div inside my html. But I am not really sure how to do it or if its even possible. Please HALP.

if you want also a label element;
for (var key in JSONObject) {
if (JSONObject.hasOwnProperty(key)) {
$('<label>')
.attr('for', JSONObject[key]["ID"])
.html(JSONObject[key]["question"])
.appendTo('wherever_you_want');
$('<textarea>')
.attr('id', JSONObject[key]["ID"])
.appendTo('wherever_you_want');
}
}

create dynamic elements input and label and then append these elements to the parent div or to the body what ever suits your requirement.
DEMO :https://jsfiddle.net/ew4mqhow/3/
<div id ="display"></div>
<script>
var textbox = document.createElement('input');
textbox.setAttribute("id", JSONObject[key]["ID"]);
var labell = document.createElement('label');
labell.setAttribute("for",JSONObject[key]["question"]);
labell.innerHTML = JSONObject[key]["question"];
document.getElementById('display').appendChild(textbox);
document.getElementById('display').appendChild(labell);
</script>

Answer by keune is perfect. One suggestion, tho - do add a prefix to foreign ID's. Just to be on safe side on case You'll assign ID's to other types of elements (ie. answers), too.
for (var key in JSONObject) {
if (JSONObject.hasOwnProperty(key)) {
$('#quizquestions')
.append($('<label>')
.attr('for', 'Q' + JSONObject[key]["ID"])
.html(JSONObject[key]["question"]))
.append($('<textarea>')
.attr('id', 'Q' + JSONObject[key]["ID"]))
}
}

Related

Jquery each loop doesn't display JSON item's properties

Edited2: Here is a pic of how one object looks like. All fields for all objects are filled.
Edited: So the problem appears to be the each loop. I console.logged data and it showed it in an array style. But for some reason, when i try to print the object's age, f.ex., it shows up as undefined.
I am doing a small script for displaying information from a json-file with jquery and ajax. I got the ajax part working (I think) but I can't get my function to print the JSON object data.
So I am trying to display JSON object's with Jquery but it doesn't do anything. The ready function prints out done and complete.
$(document).ready(function(){
$.ajax({
url: "file.json",
cache: false
}).done(function(data) {
console.log("done");
showData(data);
}).fail(function() {
console.log("error");
}).always(function() {
console.log("complete");
});
});
function showData(data) {
$.each(data.cats, function(index, kitty) {
var div = $("<div></div>");
div.addClass("catContainer");
var image = $("<img></img>");
image.addClass("catImage");
image.src="kitty.image";
var header = $("<p></p>").text(kitty.color);
header.addClass("header");
var age = $("<p></p>").text(kitty.age);
var text = $("<p></p>").text(kitty.text);
text.addClass("text");
var price = $("<p></p>").text(kitty.price);
div.append(image,header,size,text,price);
$("div#cats").append(div);
});
}
I also tried this loop but it prints 'undefined' to the div:
$(data).each(function(i, kitty) {
$('#cats').append(kitty.price);
// I am sorry, I am noob. Hope this post is according to the instructions.
One issue is with your image.src. When you set it to "kitty.image", this would literally assign that string. So instead of:
image.src = "kitty.image",
Use:
image.attr("src", kitty.image);
Or:
image[0].src = kitty.image
The latter here, since image is a jQuery Object, would not have src as an index. So we can call image[0] to get the HTML Element, that we can then assign the src.
Consider the following.
$(function() {
function showData(d, o) {
$.each(d, function(index, kitty) {
console.log("Adding Kitty", kitty);
var div = $("<div>", {
class: "catContainer"
}).appendTo(o);
$("<img>", {
class: "catImage",
src: kitty.image
}).appendTo(div);
$("<p>", {
class: "header"
}).html(kitty.color).appendTo(div);
$("<p>").html(kitty.age).appendTo(div);
$("<p>", {
class: "text"
}).html(kitty.text).appendTo(div);
$("<p>").html(kitty.price).appendTo(div);
});
}
$.ajax({
url: "file.json",
cache: false,
success: function(data) {
showData(data.cats, "#cats");
console.log("Success");
},
error: function(x, e, n) {
console.log("Error", x, e, n);
}
});
});
Based on your post, data is an Object. data.cats is an Array of Objects. So we will iterate the Array with $.each() using data.cats. I also pass in the target object ID. .appendTo() accepts a few items:
A selector, element, HTML string, array of elements, or jQuery object; the matched set of elements will be inserted at the end of the element(s) specified by this parameter.
See More: https://api.jquery.com/appendto/
It is then just a matter of creating each of the elements. With the $("<div>"), jQuery will handle wrapping the element for us. We can also pass in an Object with the attributes, like class. We can chain to the jQuery Object that is the result and would advise using .html() versus .text(), yet there is nothing wrong with doing either.

How can I populate <select> with JSON data and display values when clicked?

I've been trying to do this, but I was only able to get the data populated inside the select of HTML.
2 Questions.
Q1.
I was able to get the JSON data using AJAX from an API. (using AJAX because I learned that it doesn't need the browser to refresh to fetch new data):
$(document).ready(function() {
getDataJson();
});
function getDataJson(ajaxurl) {
$.ajax({
method: "GET",
url: "https://corona.lmao.ninja/v2/jhucsse",
datatype: "json",
success: onSuccess,
error: onError
});
}
Next I tried to populate the select in my HTML on OnSuccess:
function onSuccess(jsonReturn) {
$("#dropdown").empty();
//console.log(jsonReturn);
let dropdown = $('#dropdown');
dropdown.empty();
dropdown.append('<option selected="true" disabled>Choose Country</option>');
dropdown.prop('selectedIndex', 0);
// Populate dropdown with list of countries
$.each(jsonReturn, function (key, entry) {
dropdown.append($('<option></option>').attr('value', entry.data).text(entry.data));
});
var $dropdown = $('#dropdown'),
$objView = $('#objView'),
$docFragment = $(document.createDocumentFragment());
for (var prop in jsonReturn) {
$('<option/>', {
val: prop,
text: prop
}).appendTo($docFragment);
}
$dropdown.append($docFragment);
$dropdown.on('change', function() {
var objString = JSON.stringify(jsonReturn[$dropdown.val()]);
objString = objString.replace(/[\{\}\[\]\"]*/ig, ''); // Remove unwanted chars
objString = objString.replace(/\,/ig, '<br/>'); // Replace commas with new lines (i.e. br tags)
$objView.html(objString);
});
$dropdown.trigger('change');
}
//if JSON fails
function onError() {
$("#dropdown").html("i failed.");
}
And It worked. But then I tried to do the next step I wanted to do which is to when I click on the name of a country it should display the rest of its JSON data with names and their values.
How to display JSON data on click with JavaScript
this isn't the exact, but close enough but it's a very different(difficult?for me) solution that I couldn't understand.
Currently my dropdown looks like this:
JSFIDDLE
Now I'm intended to do this Populate HTML Table with Certain Items from a JSON Array
but with all the other JSON data like this for each country How to display JSON data on click with JavaScript
How can I resolve the rest of the scripting?
Q2. How to reduce the AJAX fetching lag?
There's a little bit of a lag/slow that I've noticed even with fewer data. Or is it just normal?
Answer for Q1
First of all, I prepare these 3 variables to make it simpler.
let jsonResponseContainer = []
let dropdown = $("#dropdown")
let objView = $("#objView")
Then prepare this when the document is ready
$(document).ready(function() {
// Initiate everything
getDataJson();
// Move dropdown change to standalone
dropdown.on('change', function() {
let chosenResponse = JSON.stringify(jsonResponseContainer[$("#dropdown").val()])
// Remove unwanted chars
chosenResponse = chosenResponse.replace(/[\{\}\[\]\"]*/ig, '');
chosenResponse = chosenResponse.replace(/\,/ig, '<br/>');
// Change objView
objView.html(chosenResponse)
})
});
Your ajax is
function getDataJson(ajaxurl) {
$.ajax({
method: "GET",
url: "https://corona.lmao.ninja/v2/jhucsse",
datatype: "json",
success: onSuccess,
error: onError
});
}
I made a function just to populate the dropdown
function populateDropdown(index, data){
let newOption = "<option value=\"" + index + "\">" + data + "</option>"
dropdown.append(newOption)
}
Major changes I made
function onSuccess(jsonReturn) {
// Populate container with ajax return directly
jsonResponseContainer = jsonReturn
// Do what you need to do
dropdown.empty();
dropdown.append('<option selected="true" disabled>Choose Country</option>');
dropdown.prop('selectedIndex', 0);
// Populate dropdown with list of countries
$.each(jsonReturn, function (key, entry) {
populateDropdown(key, entry.country);
});
}
//if JSON fails
function onError() {
$("#objView").html("i failed.");
}
Notice that I copy jsonReturn to another variable just to make sure the data now can be accessed everywhere. Next is your on-change listener was put on a loop, I moved it out of the loop. Now, I make <option> with string (you may change it with fragment if you want). Pay attention I make the value with key (array key for jsonReturn which is the same for jsonResponseContainer). When the on-change listener is evoked, it just needs to retrieve from the array to <pre>.
Answer for Q2
I don't understand about it, I suppose it is not your fault.
note: I apologize if I was using the wrong grammar.

Passing key-value pair jquery array into .NET MVC action

I have an jquery key-value pair array as following:
The array is filled when check-boxes are checked
If a checkbox is unchecked, item will be removed from there
The code for that part is:
$(document).on('click', '.chkItem', function () {
if ($(this).is(':checked')) {
product_ids[$(this).attr('id')] = "Checked";
} else {
delete product_ids[$(this).attr('id')];
}
});
This works fine, let's head onto the next part. Now I'm trying to send all these ID's from my view into a controller "Analyze" and action "Index", which looks as following:
$(".btnAnalyze").click(function () {
if (jQuery.isEmptyObject(product_ids) == true) {
alert("Array is empty");
}
else {
var postData = { values: product_ids };
$.ajax({
type: "POST",
url: "/Analyze/Index",
data: postData,
success: function (data) {
alert(data.Result);
},
dataType: "json",
traditional: true
});
}
});
And my action looks like following:
public ActionResult Index(List<string> values)
{
string id2= "";
foreach (var id in values)
{
id2= id;
}
// I'm trying to fetch the ID values here that I added into the array, but I'm not sure how...
}
With this current method the contents of List values is
"[object Object]"
which is not what I want.. I need all of the ID's sorted out nicely into the list as I send them to the Action Index...
Can someone help me out with this???
You're using an object, not an array, and it is thus saying that it's an object. You have two choices:
Use an actual array:
var product_ids = [];
$(document).on('click', '.chkItem', function () {
if ($(this).is(':checked')) {
product_ids.push($(this).attr('id'));
} else {
product_ids.splice(product_ids.indexOf($(this).attr('id')), 1);
}
});
Continue using an object and use Object.keys to get just the property names (which are the IDs in your code):
var postData = { values: Object.keys(product_ids) };
Personally, I like #1 because it's more explicit that you're capturing the ids of the checked checkboxes, and the values of the object's properties is always "Checked" rather than anything meaningful, but hey, JavaScripts' flexible like that :).
Use console.log(data.Result) to debug instead of alert(data.Result), because alert(data.Result) stringifies your variable to [object Object]. To open up console press F12

Retrieve list items from multiple lists with urls stored in an array

How do i get list items from different lists in SharePoint using javascript. Given that all my list are stored in an array. And I need to loop through the array and execute similar functions on each list.
function initializePage() {
listcollections.forEach(function (value, index) { // listcollections is the array that contains the list url for different lists
var listtitle = value.listTitle;
var siteUrl = value.siteURL;
getItemsWithCaml(siteUrl, listtitle,
function (camlItems) {
var listItemEnumerator = camlItems.getEnumerator();
while (listItemEnumerator.moveNext()) {
var EventsItem = new Events();
var listItem = listItemEnumerator.get_current();
EventsItem.eventTitle = listItem.get_item('Title');
EventsItem.eventDate = listItem.get_item('EventDate');
EventsItem.eventId = listItem.get_id();
EventsItem.eventSite = siteUrl;
EventsItem.eventList = listtitle;
EventsCollection.push(EventsItem);
}
},
function (sender, args) {
alert('An error occurred while retrieving list items:' + args.get_message());
});
})
};
function getItemsWithCaml(siteUrl, listtitle, header, success, error)
{
var hostWebContext = new SP.ClientContext(siteUrl);
var list = hostWebContext.get_web().get_lists().getByTitle(listtitle);
var caml = new SP.CamlQuery();
//Create the CAML that will return only items expiring today or later
caml.set_viewXml("<View><Query><Where><Geq><FieldRef Name=\'Expires\'/><Value Type=\'DateTime\'><Today /></Value></Geq></Where> </Query></View>");
var camlItems = list.getItems(caml);
hostWebContext.load(camlItems);
hostWebContext.executeQueryAsync(
function () {
success(camlItems);
},
error
);
};
//need to execute certain functions to format each list item
// I am not able to retrieve all list items in a single variable to be able to display data from all lists together
In the example below, I create a JavaScript object named ListDataCollection that contain a property Lists that is an array of objects.
Each of those contain a Url property whit the url of the lists I want to get the content.
Then I loop trough the array of objects and call the Sharepoint REST api for each Url.
Each time a call is complete :
I create a Data property on the current object with the data received
by the ajax call to the REST api.
I also update the current object Completed property to true.
Then I call a function named ifAllCompleted that check if all ajax calls are ended.
When all data is received, I log the word Completed on the browser console.
At this point, you have an array of objects. Each object contains the data of one Sharepoint list.
For example :
ListDataCollection.Lists[0].Data.d.results[0].Title
will contain the value of the Title Column of the first element in the first list.
If you want, you can merge all data in one array using the concat function in JavaScript.
Look at the 4 lines of code following the word Completed.
Hope this can help!
<script>
var ListDataCollection = {
Lists:[{
Url:"http://Url.Of.Your.Site.Collection/_api/web/lists/getbytitle('List1')/Items",
Completed:false
},{
Url:"http://Url.Of.Your.Site.Collection/_api/web/lists/getbytitle('List2')/Items",
Completed:false
},{
Url:"http://Url.Of.Your.Site.Collection/_api/web/lists/getbytitle('List3')/Items",
Completed:false
}]
};
function ifAllCompleted() {
for (var i=0;i<ListDataCollection.Lists.length;i++) {
if (!ListDataCollection.Lists[i].Completed) {
return false;
}
}
console.log('Completed');
var arrayOfAllData = ListDataCollection.Lists[0].Data.d.results;
arrayOfAllData = arrayOfAllData.concat(ListDataCollection.Lists[1].Data.d.results);
arrayOfAllData = arrayOfAllData.concat(ListDataCollection.Lists[2].Data.d.results);
console.log('Total elements : ' + arrayOfAllData.length);
}
$(document).ready(function(){
for (var x=0;x<ListDataCollection.Lists.length;x++) {
$.ajax({
url:ListDataCollection.Lists[x].Url,
indexValue:x,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data, status, xhr) {
ListDataCollection.Lists[this.indexValue].Data = data;
ListDataCollection.Lists[this.indexValue].Completed = true;
ifAllCompleted();
},
error: function (xhr, status, error) {
console.log('error');
}
});
}
});
</script>

How to format jquery ui autocomplete with function that returns json?

I have a function that makes an AJAX call and returns the data as JSON.
Donor.prototype.GetFriends = function(callback)
{
$.post(apiUrl + "getfriends",
{
"authentication_code" : this.authcode
},
function(response)
{
if (response)
{
callback(response.result);
}
}, "json");
}
Now in my UI I have the following:
var donor = new Donor();
$("#msg-to").autocomplete({source: function()
{
donor.GetFriends(function(response){response.friends.candidates})
}
});
But this is not working...The json is being returned in firebug, but not displaying in the autocomplte field.
result
Object { error_state=0, friends={...}, error_msg=""}
error_msg
""
error_state
0
friends
Object { candidates="[{"follow_id":"3","0":"...","6":"227.jpg"},false]", donors="[{"follow_id":"4","0":"...","6":"224.jpg"},false]"}
candidates
"[{"follow_id":"3","0":"3","user_id":"227","1":"227","following":"222","2":"222","candidate_id":"61","3":"61","firstname":"Helen","4":"Helen","lastname":"Hunt","5":"Hunt","image":"227.jpg","6":"227.jpg"},{"follow_id":"5","0":"5","user_id":"225","1":"225","following":"222","2":"222","candidate_id":"55","3":"55","firstname":"Test","4":"Test","lastname":"Candidate","5":"Candidate","image":"225.jpg","6":"225.jpg"},{"follow_id":"1","0":"1","user_id":"222","1":"222","following":"226","2":"226","candidate_id":"59","3":"59","firstname":"New","4":"New","lastname":"Candidate","5":"Candidate","image":"226.jpg","6":"226.jpg"},{"follow_id":"6","0":"6","user_id":"222","1":"222","following":"227","2":"227","candidate_id":"61","3":"61","firstname":"Helen","4":"Helen","lastname":"Hunt","5":"Hunt","image":"227.jpg","6":"227.jpg"},false]"
donors
"[{"follow_id":"4","0":"4","user_id":"224","1":"224","following":"222","2":"222","donor_id":"124","3":"124","firstname":"Just","4":"Just","lastname":"A Donor","5":"A Donor","image":"224.jpg","6":"224.jpg"},{"follow_id":"2","0":"2","user_id":"222","1":"222","following":"224","2":"224","donor_id":"124","3":"124","firstname":"Just","4":"Just","lastname":"A Donor","5":"A Donor","image":"224.jpg","6":"224.jpg"},false]"
Also the json that is returned has a candidate_id, firstname, lastname and imageUrl returned, how can I have these displayed in the results, with the friend_id being the value and the others for display?
Thanks in advance...
Couple of things:
You might need to return the array you're creating in order for the autocomplete to use it
You also need to make sure the array of objects has the correct keys for the autocomplete to use
The minimum required keys that need to available for the autocomplete to work correctly are 'label' and 'value'. Other keys can be included, and can be fetched during an event like select or change.
As an example, I might try something like the following. Adjust your GetFriends function to use the request and response callback functions provided by jQuery automatically, and then feed the formatted data that the autocomplete needs back to them:
Donor.prototype.GetFriends = function(request, response){
// this is where you can grab your search term, if need be...
var search_term = request.term;
$.post(
apiUrl + "getfriends",
{"authentication_code" : this.authcode},
function(data)
{
// process your data here into an array that the autocomplete
// will appreciate...
var autocomplete_array = [];
$.each(data.friends.candidates, function(index, candidate)
{
autocomplete_array.push(
{
label: candidate.firstname + " " + candidate.lastname,
value: candidate.user_id,
another_key: candidate.follow_id,
and_another: candidate.image
});
});
// now send the array back to the response parameter...
response(autocomplete_array);
},
"json"
);
};
Then, I'd simplify the autocomplete initializer parameters to include your function:
$("#msg-to").autocomplete({source: donor.GetFriends});
As an additional note, to get to the keys of the items, you could modify your autocomplete field to include the select or change event handlers I mentioned earlier:
$("#msg-to").autocomplete(
{
source: donor.GetFriends
select: function(event, ui){
alert("You selected: " + ui.item.label);
// or...
alert("You selected: " + ui.item.another_key);
}
});
Hope this helps, and that I didn't have a type-o's! :)
The problem is that $.post method works asynchronously. So when autocomplete tries to get data, your function makes POST call and returns empty result. To solve this try adding "async:false" option to .post call or:
Donor.prototype.GetFriends = function(callback) {
$.ajaxSetup({async:false});
$.post(apiUrl + "getfriends",
{
"authentication_code" : this.authcode
},
function(response)
{
if (response)
{
callback(response.result);
}
}, "json");
}​
You have to use the setter in the callback (see the 2nd source parameter in my examples) to add the list. If you use arrays to fill the autocomplete, the array needs objects with a label property. If this works you can add the value property too.
1.) If you can update the result of the ajax-result on server-side, change the result to:
friends
Object { candidates=Array { Object { "label": "Helen Hunt" }, ... }, donors=... }
Then your javascript can be:
var donor = new Donor();
$("#msg-to").autocomplete({
source: function(request, setter) {
donor.GetFriends(function(response) {
// set list
setter(response.friends.candidates);
});
}
});
2.) If you can't make changes at the ajax result and candidates is already an array:
var donor = new Donor();
$("#msg-to").autocomplete({
source: function(request, setter) {
donor.GetFriends(function(response) {
// create autocomplete list
var list = response.map(function(element) {
return {
label: element.firstname + ' ' + element.lastname
};
});
// set list
setter(list);
});
}
});
3.) Otherwise (if candidates is a string) [try this first]:
var donor = new Donor();
$("#msg-to").autocomplete({
source: function(request, setter) {
donor.GetFriends(function(response) {
// parse json string
var jsonresult = $.parseJSON(response);
// create autocomplete list
var list = jsonresult.map(function(element) {
return {
label: element.firstname + ' ' + element.lastname
};
});
// set list
setter(list);
});
}
});

Categories