Mapping JSON value in Javascript [duplicate] - javascript

I have a listview which is dynamically populated with offers for a store locator I am developing. The listview populates perfectly fine with a formatted list with the offer title and offer description.
I am trying to create a saved feature where the user can save offers for offline use. To do this I am transferring the database values into attributes of the dynamic listview where I can place them into variables for use in sessions/localstorage etc.
Here is my js code that defines the attributes and displays the listview.
var output1 = '';
function getoffers(data) {
var data = JSON.parse(data);
console.log(data);
$.each(data, function(index, value){
output1 += '<li offertitle='+value.offer_title+' offer-desc='+value.offer_desc+' offer-expiry='+value.expiry_date+'><h1>'+value.offer_title+'</h1><p>'+value.offer_desc+'</p><p class="ui-li-aside"><b>Expiry Date:</b>'+value.expiry_date+'</p></li>';
});
$('#offerlist').html(output1).listview().listview('refresh');
}
As you can see, I display the database values and assign them to attributes in their dynamic listview row.
I create the variables on click of the listview row where I alert each variable for testing. This is where I discover that the variable only has the first word (of what should be a paragraph).
Eg. An offer that should say "Buy one, get one free". Only returns "Buy" in the variable.
$("#offers ul").on("click", ">li", function(event, ui) {
var offertitle = $(this).closest('li').attr('offertitle');
var offerdesc = $(this).closest('li').attr('offer-desc');
var offerexpiry = $(this).closest('li').attr('offer-expiry');
alert(offertitle);
alert(offerdesc);
alert(offerexpiry);
});

You're not quoting the attribute, so only the first word is treated as part of it.
You need to set it like:
output1 += '<li offertitle="'+value.offer_title+'" offer-desc="'+value.offer_desc+'" offer-expiry="'+value.expiry_date+'"><h1>'+value.offer_title+'</h1><p>'+value.offer_desc+'</p><p class="ui-li-aside"><b>Expiry Date:</b>'+value.expiry_date+'</p></li>';
As an aside, you shouldn't be defining your own custom attributes, but rather using HTML data attributes.

Related

Standard way of building an arbitrary length table in Javascript

I'm receiving data from a websocket (live stream), and trying to put it into a table. I'm currently using the following code:
var table = document.getElementById("websocket-data");
function writeToScreen(message) {
var new_row = table.insertRow(0);
var cell1 = new_row.insertCell(0);
var cell2 = new_row.insertCell(1);
var obj = JSON.parse(message.data);
console.log(obj.value);
cell1.innerHTML = obj.id;
cell2.innerHTML = obj.value;
}
This works, and creates a new row for every JSON packet. The functionality that I am looking for is: On receipt of a JSON, if the id is not in the table, then create a row with id and value, however, if the id is already in the table, simply update the value. I've come across a few ways of doing this, but I'd like to know what the 'proper' way to do it is. I was thinking that perhaps the data should go into an array, and then the array should populate the table, but that would involve repopulating the entire table every time the array changed... I'm happy to use JQuery or similar if necessary.
You could use an array and repopulate the table every time like you said, and if the table will only ever be small then you may not run into issues with that.
One possible alternative of many is maintaining an object in the background with your ids as keys and then store the value and the table row index as values.
Something like:
var tableStore = {};
function recieveMessage(message) {
var obj = JSON.parse(message);
// if the id is not in the tableStore, add it!
if (tableStore[obj.id] === undefined) {
// insert new row into table and save the index into `newTableRowIndex`
// store a blank value (updated below) and the index in the table where it will be displayed
tableStore[obj.id] = {value: undefined, tableIndex: newTableRowIndex};
}
// if the value recieved is different than the stored value, update the row
if (obj.value !== tableStore[obj.id].value) {
tableStore[obj.id].value = obj.value; // store the new value
var row = getTableRow(tableStore[obj.id].tableIndex); // your own function to get the row based on index
// update the row to display the new information
}
}
This could be improved and made to be more organized but you should get the idea.
This way it would only update anything in the display if the new information recieved is different than the old information already stored.
This way should also perform better than using an array would if the table has the potential to get very large as you would not need to search through the entire array every time to see if the id is already stored or not. You would simply access the tableStore entry directly using the id.

Get selected data array from kendo multiselect

I am trying to get an array of the selected items from my Kendo multiselect, which is in the editor template of a kendo grid.
The multiselect code:
#(Html.Kendo().MultiSelect()
.Name("Staff")
.DataValueField("ID")
.DataTextField("FullName")
.BindTo((System.Collections.IEnumerable)ViewData["Staff"])
.Events(events => events
.Change("onChange")
)
.HtmlAttributes(new { #class = "col-md-7 details-editor" })
)
I want to extract the selected items using JQuery - specifically, I want the DataValueField, which is an integer. I have tried several things, but have been unable to get the appropriate integers, rather than the index of the item in the ViewData collection. Some of the approaches I have tried.
var data = $("#Staff").data("kendoMultiSelect").dataItems();
var data = $("#Staff").data("kendoMultiSelect").value();
I don't really know what to do from here, how to use one of the above or a different route to obtain the correct int array.
Thanks for any help!
The answer is simpler than you would think.
$('#Staff').val();
That will return a comma delimited list of whatever is in your .DataValueField. In your case, a comma delimted list of 'ID'.
To get the IDs of the selected items, you can write your onChange method as follows:
var onChange = function(e) {
var arrayOfNames = this.value();
// Do other stuff here...
};
Documentation for the change event which gets fired can be found here.
I've also written a working example here.
Add a .Select("onSelect") event to the Multiselect and append the Value to hidden element every time when user selects the items using:
function onSelect(e) {
var item = e.item;
var text = item.text();
var $data = $('#myHidden');
$data.val($data.val() + text);
};

JavaScript - Retrieve variable value generated inside the for loop, externally

Well, I am working with a rest API that fetch information from the same database, but two different tables:
Table #1 contains(Outputs JSON results that contains the below objects):
id
name
type
Table #2 contains(Outputs JSON results that contains the below objects):
id
value (real-time, updated periodically)
What I want to do is to compare the id in Table #1 and compare it to id
in Table #2 and if there is a match between the two id's outputs the sum of (value) from Table #2 with all the values having the same id.
Until now what I am able to do is the following:
File1.js
require('File2.js');
for (a in metricsData){
var metricsID = metricsData[a].id;
}
/* Certainly the below code is not working, but I don't know if it should
be done this way or it can be much more better.
Can't get the values of both metricsID & idFromLoad
if(metricsID === idFromLoad) {
var sum += value;
console.log('The new sum is : '+sum)
} */
File2.js
for(var i in load.updates){
var idFromLoad = load.updates[i].id;
var newVal = load.updates[i].value;
}
So, the big question is how to get the values of both metricsID & idFromLoad outside of the for loop? Is there a better way to achieve what I am trying to do?
What you are trying to accomplish is a little confusing, but to answer the question as described in the title of this post...
Because you have the variable defined inside the loop, it only exists inside the loop. If you want to "remember" the value outside of the loop, you would need to define it outside:
var metricsID;
for (a in metricsData){
metricsID = metricsData[a].id;
}
Note though, that outside the loop, it's value will equal the id of the last item in the loop.
If you are looking for an easy way to look up values in both tables, what you could do is loop through each once and create a map keyed off the id so that you can easily retrieve the value based on the id.
var updatesMap = {};
for(var i in load.updates){
var idFromLoad = load.updates[i].id;
updatesMap[idFromLoad] = load.updates[i].value;
}
Then in your other loop:
for (a in metricsData){
var metricsID = metricsData[a].id;
var updateValue = updatesMap[meticsID]; //this is the value from the other table
}

How to retrieve only lookup id in Sharepoint with JSOM

I'm trying to get list items from a SharePoint list with specific fields only.
The list contains lookup fields to other lists and I need the LookupId only for these.
I know two cases to narrow down the returned fields.
The first is with CAML. I can use the LookupId="TRUE" option to suppress the LookupValue in this case, but the server returns other system fields (eg. Modified By, Created By, etc.) which I don't need to.
The second is using 'Include' in ClientContext.load method. In this case the server not sends the system fields but I don't know how to specify (if possible) to receive the LookupId only for lookup fields.
I tried several versions in Include (project.id, projectId, project.lookupId, project.Inlude(id)) but none of them worked.
So, my question is: how to retrieve only specified fields of a SharePoint list with LookupIds only for lookup fields?
You were very close to archive the desired result, you need to combine two techniques in order to retrieve id part of lookup value as demonstrated below:
var ctx = SP.ClientContext.get_current();
var list = ctx.get_web().get_lists().getByTitle(listTitle);
var items = list.getItems(createLookupQuery('Project'));
ctx.load(items,'Include(Project)');
ctx.executeQueryAsync(
function(){
if(items.get_count() > 0){
var item = items.getItemAtIndex(0);
console.log(item.get_fieldValues()['Project'].get_lookupId());
}
},
function(sender,args)
{
console.log(args.get_message());
});
function createLookupQuery(lookupFieldName){
var qry = new SP.CamlQuery();
qry.set_viewXml("<View><ViewFields><FieldRef Name='" + lookupFieldName + "' LookupId='TRUE' /></ViewFields></View>");
return qry;
}
In CAML query we specify attribute LookupId='TRUE' to retrieve Id
part of lookup field value
since CAML query includes also system field values, we utilize
SP.ClientContext.load method to return specific field value
only
how to retrieve only specified fields of a SharePoint list with
LookupIds only for lookup fields?
The question is a bit unclear, but assuming you want to fetch the lookup id, you can do as follows.
Suppose you've retrieved the SP.ListItem with JSOM and stored it in to a variable, your lookup field will be representeed by a SP.LookupFieldValue object.
You can access it from the retrieved item object as below.
var lookupFieldValue = item.get_item('FieldName');
var lookupId = lookupFieldValue.get_lookupId();

Variable from attribute only displays the first word

I have a listview which is dynamically populated with offers for a store locator I am developing. The listview populates perfectly fine with a formatted list with the offer title and offer description.
I am trying to create a saved feature where the user can save offers for offline use. To do this I am transferring the database values into attributes of the dynamic listview where I can place them into variables for use in sessions/localstorage etc.
Here is my js code that defines the attributes and displays the listview.
var output1 = '';
function getoffers(data) {
var data = JSON.parse(data);
console.log(data);
$.each(data, function(index, value){
output1 += '<li offertitle='+value.offer_title+' offer-desc='+value.offer_desc+' offer-expiry='+value.expiry_date+'><h1>'+value.offer_title+'</h1><p>'+value.offer_desc+'</p><p class="ui-li-aside"><b>Expiry Date:</b>'+value.expiry_date+'</p></li>';
});
$('#offerlist').html(output1).listview().listview('refresh');
}
As you can see, I display the database values and assign them to attributes in their dynamic listview row.
I create the variables on click of the listview row where I alert each variable for testing. This is where I discover that the variable only has the first word (of what should be a paragraph).
Eg. An offer that should say "Buy one, get one free". Only returns "Buy" in the variable.
$("#offers ul").on("click", ">li", function(event, ui) {
var offertitle = $(this).closest('li').attr('offertitle');
var offerdesc = $(this).closest('li').attr('offer-desc');
var offerexpiry = $(this).closest('li').attr('offer-expiry');
alert(offertitle);
alert(offerdesc);
alert(offerexpiry);
});
You're not quoting the attribute, so only the first word is treated as part of it.
You need to set it like:
output1 += '<li offertitle="'+value.offer_title+'" offer-desc="'+value.offer_desc+'" offer-expiry="'+value.expiry_date+'"><h1>'+value.offer_title+'</h1><p>'+value.offer_desc+'</p><p class="ui-li-aside"><b>Expiry Date:</b>'+value.expiry_date+'</p></li>';
As an aside, you shouldn't be defining your own custom attributes, but rather using HTML data attributes.

Categories