I am creating a services cart at client side
where services are grouped inside 3 level of groupings like
product[SECTION] [SERVICE] [ITEM]
product['carpet']['cleaning']['room'] = {'qty':2,'price':15};
product['carpet']['cleaning']['hall'] = {'qty':1,'price':10};
product['carpet']['protecting']['hall'] = {'qty':1,'price':10};
product['carpet']['deodorize']['hall'] = {'qty':1,'price':10};
product['leather']['cleaning']['sofa'] = {'qty':1,'price':10};
want to generate above structure of json.
my text boxes looks like below notice data-section data-service data-tem and data-price
<input type="text" class="form-control input-number"
data-price="15" data-section="carpet" data-item="room" data-service="protect" />
My JS code is as below, but it adds only current item while overwriting all other services and sections.
$(function(){
$('.input-number').change(function(){
var section = $(this).attr('data-section');
var item = $(this).attr('data-item');
var service = $(this).attr('data-service');
var qty = $(this).val();
var unitprice = $(this).attr('data-unitprice');
addProduct(section,item,service,qty,unitprice);
});
});
function addProduct(section,item,service,qty,unitprice){
let products = {};
if(localStorage.getItem('products')){
products = JSON.parse(localStorage.getItem('products'));
}
products['"'+section+'"'] =
{
['"'+service+'"'] : {
['"'+item+'"'] : {
'unitprice' : unitprice, 'qty': qty
}
}
};
localStorage.setItem('products', JSON.stringify(products));
}
How can I append only instead of overwriting nested items?
EDITED
I have edited my add product function as below but still not getting desired result
function addProduct(section,item,service,qty,unitprice){
let products = {};
if(localStorage.getItem('products')){
products = JSON.parse(localStorage.getItem('products'));
}
var v = {
[service] : {
[item] :{
"qty":qty,'unitprice':unitprice
}
}
};
products.push( section, v );
localStorage.setItem('products', JSON.stringify(products));
}
Object.prototype.push = function( key, value ){
if(typeof value === 'object'){
var k = Object.keys(value)[0];
value.push( k, value[k] );
}
this[ key ] = value;
return this;
}
First of all that is not a good way to store your data.
Here's a better way to store your data.
It's much more easy to understand if you see it like an object cause in javascript it's the same thing
//example this 2 data is store the same way in javascript
var product['carpet']['cleaning']['room'] = {'qty':2,'price':15};
var product = [{
carpet: {
cleaning: {
room: {'qty':2,'price':15}
}
}
}]
// my solution would be just save section, service and item in the object, example:
var product = [];
var v = {
section: 'carpet',
service: 'cleaning',
item: 'room'
qty:2,
price:15
}
product.push(v)
Related
I need to show the list in the select box based on the another input.
On click on the SubCategory column, its showing the selected value in the dropdown. But its not showing in the table.
You can see the table in the below image. First image its not showing the data in the display, in the second image its showing the value selected
Anything missed. Any help please..
Attached the working code.
var comboEditor = function (cell, onRendered, success, cancel, editorParams) {
//Getting the other select value, based on the value this select need to show the list
let otherCellValue = cell.getData().ForumCourt;
cboData = []; //Store last values based on another cell value
var currentlyAdded = [];
var editor = document.createElement("select");
arrayOfValues2 = caselocationData.filter(function(r){return true;});
var filteredArrayOfValues = arrayOfValues2.filter(function(r){ return r[0]=== otherCellValue});
// addUniqueOptionsToDropdownList(select2_Sub, filteredArrayOfValues,1);
filteredArrayOfValues.forEach(function(r){
if(currentlyAdded.indexOf(r[0]) === -1) {
currentlyAdded.push(r[1]);
var item = {};
item.key = r;
item.name = r[1];
cboData.push(item);
}
});
for (var i = 0; i < cboData.length; i++) {
var opt = document.createElement('option');
opt.value = cboData[i].key;
opt.innerHTML = cboData[i].name;
editor.appendChild(opt);
}
editor.style.padding = "0px";
editor.style.width = "100%";
editor.style.boxSizing = "border-box";
editor.value = cell.getValue();
onRendered(function () {
editor.focus();
editor.style.css = "100%";
});
function successFunc() {
success(editor.value);
}
editor.addEventListener("change", successFunc);
editor.addEventListener("blur", successFunc);
return editor;
};
The results of my query look like:
{
col1: [values],
col2: [values]
}
Is there a way to get my query to return as a list of rows objects?
The best way is to write a function to convert your query response.
One example:
function transformColumnSchemaToRowSchema(data) {
var keys = _.keys(data);
var arrays = _.values(data);
var arrayOfPropertyLists = _.zip.apply(_, arrays);
var arrayOfObjects = _.map(arrayOfPropertyLists, function(list) {
var obj = {};
_.each(keys, function(key, i) {
obj[key] = list[i];
});
return obj;
});
return arrayOfObjects;
}
Or a more compact version:
var data = {{q_some_query}};
delete data['_response']
var newdata = _.zip.apply(_, _.values(data)).map((val) => _.zipObject(_.keys(data), val));
After you convert to this format, you might want to convert back to the original format (for example, if you want to put the data into a table widget in Slate). This is how that can be done:
var original_fmt = {};
_.forEach(_.keys(newdata[0]), function(k) {
original_fmt[k] = _.map(newdata, k);
});
// use original_fmt
I want to bind my ng-model with JSON object nested key where my key is in a variable.
var data = {"course":{"sections":{"chapter_index":5}}};
var key = "course['sections']['chapter_index']"
Here I want to get value 5 from data JSON object.
I found the solution to convert "course.sections.chapter_index" to array notation like course['sections']['chapter_index'] this. but don't know how to extract value from data now
<script type="text/javascript">
var BRACKET_REGEXP = /^(.*)((?:\s*\[\s*\d+\s*\]\s*)|(?:\s*\[\s*"(?:[^"\\]|\\.)*"\s*\]\s*)|(?:\s*\[\s*'(?:[^'\\]|\\.)*'\s*\]\s*))(.*)$/;
var APOS_REGEXP = /'/g;
var DOT_REGEXP = /\./g;
var FUNC_REGEXP = /(\([^)]*\))?$/;
var preEval = function (path) {
var m = BRACKET_REGEXP.exec(path);
if (m) {
return (m[1] ? preEval(m[1]) : m[1]) + m[2] + (m[3] ? preEval(m[3]) : m[3]);
} else {
path = path.replace(APOS_REGEXP, '\\\'');
var parts = path.split(DOT_REGEXP);
var preparsed = [parts.shift()]; // first item must be var notation, thus skip
angular.forEach(parts, function (part) {
preparsed.push(part.replace(FUNC_REGEXP, '\']$1'));
});
return preparsed.join('[\'');
}
};
var data = {"course":{"sections":{"chapter_index":5}}};
var obj = preEval('course.sections.chapter_index');
console.log(obj);
</script>
Hope this also help others. I am near to close the solution,but don't know how can I get nested value from JSON.
This may be a good solution too
getDeepnestedValue(object: any, keys: string[]) {
keys.forEach((key: string) => {
object = object[key];
});
return object;
}
var jsonObject = {"address": {"line": {"line1": "","line2": ""}}};
var modelName = "address.line.line1";
var result = getDescendantPropValue(jsonObject, modelName);
function getDescendantPropValue(obj, modelName) {
console.log("modelName " + modelName);
var arr = modelName.split(".");
var val = obj;
for (var i = 0; i < arr.length; i++) {
val = val[arr[i]];
}
console.log("Val values final : " + JSON.stringify(val));
return val;
}
You are trying to combine 'dot notation' and 'bracket notation' to access properties in an object, which is generally not a good idea.
Source: "The Secret Life of Objects"
Here is an alternative.
var stringInput = 'course.sections.chapter_index'
var splitInput = stringInput.split(".")
data[splitInput[1]]][splitInput[2]][splitInput[3]] //5
//OR: Note that if you can construct the right string, you can also do this:
eval("data[splitInput[1]]][splitInput[2]][splitInput[3]]")
Essentially, if you use eval on a string, it'll evaluate a statement.
Now you just need to create the right string! You could use the above method, or tweak your current implementation and simply go
eval("data.course.sections.chapter_index") //5
Source MDN Eval docs.
var data = {
"course": {
"sections": {
"chapter_index": 5
}
}
};
var key = "course['sections']['chapter_index']";
var keys = key.replace(/'|]/g, '').split('[');
for (var i = 0; i < keys.length; i++) {
data = data[keys[i]];
}
console.log(data);
The simplest possible solution that will do what you want:
var data = {"course":{"sections":{"chapter_index":5}}};
var key = "course['sections']['chapter_index']";
with (data) {
var value = eval(key);
}
console.log(value);
//=> 5
Note that you should make sure key comes from a trusted source since it is eval'd.
Using with or eval is considered dangerous, and for a good reason, but this may be one of a few its legitimate use cases.
If you don't want to use eval you can do a one liner reduce:
var data = {"course":{"sections":{"chapter_index":5}}};
var key = "course['sections']['chapter_index']"
key.split(/"|'|\]|\.|\[/).reduce((s,c)=>c===""?s:s&&s[c], data)
I have two textbox(goalText and goalText1) and a button(goalreach) in my html.
My aim : When I enter numeric value in 1 textbox(goalText), it should be converted to json and be stored. So even after 5 days when I run the application, it should be stored. Now when I enter the numeric value, in other textbox(goalText1) and it matches, I am simply displaying the message match. This is the demo, I am trying so that I can know that value can be stored in json and can be retrieved when necessary. I have written the code as follow:
$("#goalreach").click(function () {
var contact = new Object();
contact.goalDist = "$("#goalText.value ").val()";
var jsonText = JSON.stringify(contact);
if (jsonText == ($("#goalText1.value").val())) {
document.getElementById('divid').innerHTML = 'Match';
}
});
I know, I have made many simple mistakes of brackets and " too, but I am a newbie, If you can help me out.
First, you have to compare either 2 objects or 2 strings, and in goalDist, you should store the value (BTW, you get the jQuery object with $("#goalText") and the value with somejQueryObject.val() moreover this is generally equivalent to document.getElementById("goalText").value)...
This can be done like this :
$("#goalreach").click(function () {
// Create an object with the single property "goalDist"
var contact = { goalDist : $("#goalText").val() };
// Makes it be a string (it will in this simple example : `"{"goalDist":<the value of goalTest>}"`
var jsonText = JSON.stringify(contact);
// Creates a string from an equivalent object bound on the second field
var jsonText2 = JSON.stringify({ goalDist : $("#goalText2").val() });
// Compares the 2 strings
if (jsonText === jsonText2) {
document.getElementById('divid').innerHTML = 'Match';
}
});
TRY THIS
$("#goalreach").click(function () {
var contact = new Object();
var goalDist = '$("#goalText.value").val()';
var jsonText = JSON.stringify(contact.goalDist);
if(jsonText==($("#goalText1.value").val()))
{
document.getElementById('divid').innerHTML = 'Match';
}
});
Try the following code:
$("#goalreach").click(function () {
var contact = new Object();
contact.goalDist = $("#goalText").val();
var jsonText = JSON.stringify(contact);
if (jsonText == ($("#goalText1").val())) {
document.getElementById('divid').innerHTML = 'Match';
}
});
OR
$("#goalreach").click(function () {
var goalText = $("#goalText").val();
var goalText1 = $("#goalText1").val();
if (goalText == goalText1) {
document.getElementById('divid').innerHTML = 'Match';
}
});
I have a Java object where the person object contains a displayName object. I have converted it to a JSON object for my JSP. The data looks like the following:
var people = [
{"id":52959,"displayName":{"firstName":"Jim","lastName":"Doe","middleName":"A"},"projectId":50003,"grade":"8","statusCode":"A","gradYear":2016,"buyer":false},
{"id":98765,"displayName":{"firstName":"Jane","lastName":"Doe","middleName":"Z"},"projectId":50003,"grade":"8","statusCode":"A","gradYear":2016,"buyer":true}
];
I want to bind my columns to the name properties that reside within the displayName object, but I am cannot get the column definition to recognize where the data resides. Here is an example of my firstName column definition:
{id: 'displayName.firstName', field: 'displayName.firstName', name: 'First Name',
width: 110, sortable: true, editor: TextCellEditor, formatter: SpaceFormatter,
cssClass: '', maxLength: 250, editable: true}
The view does not render the names although the data is there. Is it possible to bind a column to an object property that resides within another object? If so, what am I doing wrong?
Slickgrid doesn't support this capability by default, but you can workaround it by adding custom value extractor to your options object:
var options = {
dataItemColumnValueExtractor: function(item, columnDef) {
var names = columnDef.field.split('.'),
val = item[names[0]];
for (var i = 1; i < names.length; i++) {
if (val && typeof val == 'object' && names[i] in val) {
val = val[names[i]];
} else {
val = '';
}
}
return val;
}
}
var grid = new Slick.Grid($("#slickgrid"), data, columns, options);
The code is tested with slickgrid 2.0 and is working just fine. Unfortunately seems that slickgrid code is a bit inconsistent and editors don't take into account this option, so this solution is usable only if you will display the data without editing.
I know this is a bit old... but my work around is to do a pre-process on my items. Basically, flattening the model out:
var preProcessItems = function (items) {
var newItems = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
item['firstName'] = item['displayName']['firstName'];
newItems[i] = item;
}
return newItems;
};
/// when the value is updated on the flat structure, you can edit your deep value here
var fNameFormatter = function (row, cell, value, columnDef, dataContext) {
// datacontext.displayName.firstName = value;
return value ? value : "";
};
This problem seems to be more a of a data modeling issue though.