I'm basically trying to bulk insert or update (on duplicate key) a JSON array of objects in a MySQL table using NodeJS. Sometimes JSON objects in array contain different key-value pairs.
A possible solution could be to loop over the JSON array first and then search each object for every key hardcoded from another array (corresponding to columns in table) then push result values in new array of arrays. In case a key does not exist in JSON object then fill with a "NULL" value.
Many thanks for any advice in advance!
var keys = ['customerId','subscriptionId','billingMethod','skuId','creationTime','planName','isCommitmentPlan','startTime','endTime','numberOfSeats','licensedNumberOfSeats','maximumNumberOfSeats','isInTrial','trialEndTime','renewalType','purchaseOrderId','status''customerDomain','skuName','suspensionReasons','dealCode'];
var demo_api = [{
"kind": "reseller#subscription",
"customerId": "C0123456",
"subscriptionId": "123",
"billingMethod": "ONLINE",
"skuId": "Google-Apps-Unlimited",
"creationTime": "1331647980142",
"plan": {
"planName": "ANNUAL",
"isCommitmentPlan": true,
"commitmentInterval": {
"startTime": "1331647980142",
"endTime": "1363183980142"
}
},
"seats": {
"kind": "subscriptions#seats",
"numberOfSeats": 10,
"licensedNumberOfSeats": 10,
"maximumNumberOfSeats": 500
},
"trialSettings": {
"isInTrial": false
},
"renewalSettings": {
"kind": "subscriptions#renewalSettings",
"renewalType": "SWITCH_TO_PAY_AS_YOU_GO"
},
"purchaseOrderId": "my_example.com_annual_1",
"status": "ACTIVE",
"customerDomain": "my_example.com",
"skuName": "G Suite Business"
},
{
"kind": "reseller#subscription",
"customerId": "D0123456",
"subscriptionId": "456",
"billingMethod": "ONLINE",
"skuId": "Google-Apps-For-Business",
"creationTime": "1331647980142",
"plan": {
"planName": "FLEXIBLE",
"isCommitmentPlan": false
},
"seats": {
"kind": "subscriptions#seats",
"licensedNumberOfSeats": 0,
"maximumNumberOfSeats": 10
},
"trialSettings": {
"isInTrial": false
},
"purchaseOrderId": "my_example_flex_1",
"status": "ACTIVE",
"customerDomain": "my_example2.com",
"skuName": "G Suite Business"
}];
Desired result:
var result = [
["C0123456", "123", "ONLINE", "Google-Apps-Unlimited", "1331647980142", "ANNUAL", true, "1331647980142", "1363183980142", 10, 10, 500, false, "NULL", "SWITCH_TO_PAY_AS_YOU_GO", "my_example.com_annual_1", "ACTIVE", "my_example.com", "G Suite Basic", "NULL", "NULL"],
["D0123456", "456", "ONLINE", "Google-Apps-For-Business", "1331647980142", "FLEXIBLE", false, "NULL", "NULL", "NULL", 0, 0, false, "NULL", "NULL", "my_example_flex_1", "ACTIVE", "my_example2.com", "G Suite Business", "NULL", "NULL"]
];
you can try something like this:
var myArray = new Array();
data.forEach((player) => {
console.log(player.id);
console.log(player);
var playerModel ={
id : player.id,
firstname : player.firstname,
lastname : player.lastname,
position : player.position,
price : player.price,
appearences : player.appearences,
goals : player.goals,
assists : player.assists,
cleansheets : player.cleansheets,
redcards : player.redcards,
yellowcards : player.yellowcards,
image : player.image,
clubid : player.clubid,
};
console.log("model"+playerModel.position);
myArray.push(playerModel);
});
Here you need to change the model player in my code by a model created by you , and replace like this, just follow your json endpoint :
var Mymodel = {
bind: player.bind,
............
....
}
the last step is that myArray is your results array , you need to loop it to see results
for(let item of myArray) {
console.log(item);
console.log(item.bind);
.......................
}
Related
I've seen this question in several places but still can't figure this out.
Using ramda, how can I filter the following object to return the records that are true for tomatoes?
[
{
"id": "a",
"name": "fred",
"food_prefs": {
"tomatoes": true,
"spinach": true,
"pasta": false
},
"country": "singapore"
},
{
"id": "b",
"name": "alexandra",
"food_prefs": {
"tomatoes": false,
"spinach": true,
"pasta": true
},
"country": "france"
},
{
"id": "c",
"name": "george",
"food_prefs": {
"tomatoes": true,
"spinach": false,
"pasta": false
},
"country": "argentina"
}
]
Storing this array as myData object, I thought that the following should work:
const R = require("ramda")
const lovesTomatoes = R.pipe ( // taken from: https://stackoverflow.com/a/61480617/6105259
R.path (["food_prefs"]),
R.filter (R.prop ("tomatoes"))
)
console.log(lovesTomatoes(myData))
But I end up with the error:
if (typeof obj[methodNames[idx]] === 'function') {
What am I doing wrong?
EDIT
The answers provided by #Ori Drori and #ThanosDi are both great, but I want to emphasize that a pipe-based solution would be ideal because I have follow-up steps I wish to carry on the filtered array. Consider for example the following array. It's similar the one above, but includes more data: year_born and year_record.
[
{
"id": "a",
"name": "fred",
"year_born": 1995,
"year_record": 2010,
"food_prefs": {
"tomatoes": true,
"spinach": true,
"pasta": false
},
"country": "singapore"
},
{
"id": "b",
"name": "alexandra",
"year_born": 2002,
"year_record": 2015,
"food_prefs": {
"tomatoes": false,
"spinach": true,
"pasta": true
},
"country": "france"
},
{
"id": "c",
"name": "george",
"year_born": 1980,
"year_record": 2021,
"food_prefs": {
"tomatoes": true,
"spinach": false,
"pasta": false
},
"country": "argentina"
}
]
So, for example, to answer a full question such as "for those who love tomatoes, what is the average age at the time of the record creation?"
we would need to:
filter the records that love tomates;
extract the elements year_born and year_record
get the difference between values
take the average of the differences
Therefore, using a pipe would be very beneficial.
What went wrong?
You try to get the value of food_prefs out of the array. Since the array doesn't have this key - R.path (["food_prefs"]) is undefined, and then you try to filter this undefined value.
How to solve this problem?
Filter the array, and use R.path to get the tomatoes value.
const { filter, path, identity } = R
const lovesTomatoes = filter(path(['food_prefs', 'tomatoes']))
const data = [{"id":"a","name":"fred","food_prefs":{"tomatoes":true,"spinach":true,"pasta":false},"country":"singapore"},{"id":"b","name":"alexandra","food_prefs":{"tomatoes":false,"spinach":true,"pasta":true},"country":"france"},{"id":"c","name":"george","food_prefs":{"tomatoes":true,"spinach":false,"pasta":false},"country":"argentina"}]
const result = lovesTomatoes(data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt+Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Filtering using a pipe:
Using R.pipe. I wouldn't go this way for a simple filter by nested properties, but you can use a Schwartzian transform. The idea is to create a new array if pairs [value of tomatoes, original object], filter by the value of tomatoes, and then extract the original object:
const { pipe, map, applySpec, path, identity, filter, last, head } = R
const lovesTomatoes = pipe(
map(applySpec([path(['food_prefs', 'tomatoes']), identity])), // create an array of [value of tomatoes, original object]
filter(head), // filter by the value of the tomatoes
map(last) // extract the original object
)
const data = [{"id":"a","name":"fred","food_prefs":{"tomatoes":true,"spinach":true,"pasta":false},"country":"singapore"},{"id":"b","name":"alexandra","food_prefs":{"tomatoes":false,"spinach":true,"pasta":true},"country":"france"},{"id":"c","name":"george","food_prefs":{"tomatoes":true,"spinach":false,"pasta":false},"country":"argentina"}]
const result = lovesTomatoes(data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt+Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
How to combine the 1st lovesTomatoes filtering function in a pipe:
However, if you just need the pipe to perform other operations on the filtered array, use the filter as one of the steps:
const { filter, path, identity, pipe, map, prop, uniq } = R
const lovesTomatoes = filter(path(['food_prefs', 'tomatoes']))
const countriesOfTomatoLovers = pipe(
lovesTomatoes,
map(prop('country')),
uniq
)
const data = [{"id":"a","name":"fred","food_prefs":{"tomatoes":true,"spinach":true,"pasta":false},"country":"singapore"},{"id":"b","name":"alexandra","food_prefs":{"tomatoes":false,"spinach":true,"pasta":true},"country":"france"},{"id":"c","name":"george","food_prefs":{"tomatoes":true,"spinach":false,"pasta":false},"country":"argentina"}]
const result = countriesOfTomatoLovers(data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt+Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
const myData = [
{
"id": "a",
"name": "fred",
"food_prefs": {
"tomatoes": true,
"spinach": true,
"pasta": false
},
"country": "singapore"
},
{
"id": "b",
"name": "alexandra",
"food_prefs": {
"tomatoes": false,
"spinach": true,
"pasta": true
},
"country": "france"
},
{
"id": "c",
"name": "george",
"food_prefs": {
"tomatoes": true,
"spinach": false,
"pasta": false
},
"country": "argentina"
}
];
const lovesTomatoes = filter(pathOr(false, ['food_prefs','tomatoes']));
lovesTomatoes(myData);
Ramda REPL
Ramda comes with a whole suite of predicates built-in already,
one of them that I'd use here is pathEq.
I'd suggest to adopt a map and reduce kind of approach, whereas the match function is separated from the actual aggregation...
Collect your data point
Reduce it to the information you need
const tomatoLovers = R.filter(
R.pathEq(['food_prefs', 'tomatoes'], true),
);
const avgAge = R.pipe(R.pluck('age'), R.mean);
const data = [{
"id": "a",
age: 16,
"name": "fred",
"food_prefs": {
"tomatoes": true,
"spinach": true,
"pasta": false
},
"country": "singapore"
},
{
"id": "b",
age: 66,
"name": "alexandra",
"food_prefs": {
"tomatoes": false,
"spinach": true,
"pasta": true
},
"country": "france"
},
{
"id": "c",
age: 44,
"name": "george",
"food_prefs": {
"tomatoes": true,
"spinach": false,
"pasta": false
},
"country": "argentina"
}
]
console.log(
'Average age of tomato lovers is:',
R.pipe(tomatoLovers, avgAge) (data),
);
console.log(
'They are the tomato lovers',
R.pipe(tomatoLovers, R.pluck('name')) (data),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.js" integrity="sha512-ZZcBsXW4OcbCTfDlXbzGCamH1cANkg6EfZAN2ukOl7s5q8skbB+WndmAqFT8fuMzeuHkceqd5UbIDn7fcqJFgg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
I have result json file with 10000 of lines. inside the one array object there are some unnecessary json object i need remove. I have tried so many ways but it's didn't work for me. herewith the piece line of json file
[
{
"product_id": "easybridge",
"errors": []
},
{
"product_id": "learningstudio",
"errors": []
},
{
"product_id": "pearsontestprep",
"errors": []
},
{
"product_id": "productization",
"errors": []
},
{
"product_id": "equella",
"errors": [
{
"property": "instance.test_ids[1]",
"message": "requires property \"maintenance\"",
"schema": {
"$id": "#/properties/test_ids/items",
],
"properties": {
"trend": {
"$id": "#/properties/test_ids/items/properties/trend",
"examples": [
true
]
},
"display": {
"$id": "#/properties/test_ids/items/properties/display",
"type": "boolean",
"examples": [
true
]
},
"test_id": {
"$id": "#/properties/test_ids/items/properties/test_id",
"type": "string",
},
"test_name": {
"$id": "#/properties/test_ids/items/properties/test_name",
"type": "string",
},
"maintenance": {
"$id": "#/properties/test_ids/items/properties/maintenance",
"type": "boolean",
]
},
"instance": {
"trend": false,
"display": false,
"test_id": "8597ae3c-e2a9-45c7-b279-bde1710681be",
"test_name": "Equella Pearsonresearch Ping Test",
"nrAlertStatus": "enabled",
"test_locations": [
{
"alert_state": false,
"location_name": "AWS_US_WEST_2",
"location_label": "Portland, OR, USA",
"included_to_health": false
}
],
"included_to_health": false,
"critical_alert_threshold": 60
},
"name": "required",
"argument": "maintenance",
"stack": "instance.test_ids[1] requires property \"maintenance\""
{
"product_id": "easybridge",
"errors": []
},
I just need only
{
"product_id": "equella",
"errors": [
{
"property": "instance.test_ids[1]",
"message": "requires property \"maintenance\"",
}
},
if the errors json array is not empty. i don't need even this json how can i remove "schema" json object and other unnecessary json object and arrays specially "schema" json object using java script or java. please help
Loop through the array, look at each object, and create a new array by copying over the data you need.
For instance, I'm taking it you don't care about an object if its array of errors is empty, and that you don't care about the schema ever:
let newJSON = [];
//Assume the json variable is the parsed JSON file you posted.
for (let element of json) {
//Must have at least one error
if (element.errors.length > 0) {
//Create a new object
let newObj = {
"product_id" : element.product_id,
"errors" : []
};
//Add each errror
for (let error of element.errors) {
//Only copy across what we need
newObj.errors.push({
"property" : error.property,
"message" : error.message
});
}
//Add object to our new array of JSON
newJSON.push(newObj);
}
}
//newJSON is your processed JSON output
The easiest solution can be:
const records = [{
"product_id": "learningstudio",
"errors": []
},
{
"product_id": "pearsontestprep",
"errors": []
},
{
"product_id": "equella",
"errors": [{
"property": "instance.test_ids[1]",
"message": "requires property \"maintenance\"",
"schema": {
"$id": "#/properties/test_ids/items",
}
}]
}];
const filteredRecords = records.map((record) => {
record.errors = record.errors.map((error) => {
return {property: error. property, message: error.message};
});
return record;
});
console.log(filteredRecords);
You can use map and destructuring assignment to capture only desired properties
let json = [{"product_id": "equella", "errors": [{"property": "instance.test_ids[1]","message": "requires property \"maintenance\"",'xyz': 'not needed','useless': 'not needed',},{'xyz': 'not needed',}]},]
let op = json.map(({product_id,errors}) =>{
let { property, message } = errors[0]
return { product_id, errors: {property,message}}
})
console.log(op)
I'm trying to test if one array contains an id which exists in another array. Here's the first Array:
var ids = [
"N06Jrz5hx6Q9bcVDBBUrF3GKSTp2",
"eLLfNlWLkTcImTRqrYnU0nWuu9P2"
]
And here's an example of how the user object looks like:
var userExample = {
"category": "Chemia",
"coins": 100,
"friends": {},
"level": "Liceum",
"newAnswers": false,
"nickname": "czainusek",
"notifications": true,
"safety": true,
"tagID": "drawable/icon_other1",
"tasksUploaded": 0,
"works": {
"-LI1z-yO4MJnPwrdwHGl": "-LI1z-tB6EpqIhJwzchP",
"-LIHAwCpc84UQqGeT1bU": "-LIHAw8RuTZxfgz0ef8G",
"-LIHB2Ov5B-4XqpM79Av": "-LIHB2IPmMqOxa3UPFxs"
},
"id": "Nqez1dKRJ6aEpOb4BuUOK75iJoJ2"
}
And I have an array of said objects. They all look like this:
var usersExamples = [
{
"category": "Chemia",
"coins": 100,
"friends": {},
"level": "Liceum",
"newAnswers": false,
"nickname": "czainusek",
"notifications": true,
"safety": true,
"tagID": "drawable/icon_other1",
"tasksUploaded": 0,
"works": {
"-LI1z-yO4MJnPwrdwHGl": "-LI1z-tB6EpqIhJwzchP",
"-LIHAwCpc84UQqGeT1bU": "-LIHAw8RuTZxfgz0ef8G",
"-LIHB2Ov5B-4XqpM79Av": "-LIHB2IPmMqOxa3UPFxs"
},
"id": "Nqez1dKRJ6aEpOb4BuUOK75iJoJ2"
},
{
"coins": 20,
"friends": {},
"level": "Gimnazjum",
"newAnswers": false,
"nickname": "Tomasz ",
"notifications": true,
"safety": true,
"tagID": "drawable/emot_icons1",
"tasksUploaded": 5,
"id": "SAlVGjXIagdDuJrHYO4i6LwzUql2"
}
]
So knowing this I tried something like this:
console.log(reportIds.includes(users.map(user => user.id)));
This returned false. But if I try an id like this:
console.log(reportIds.includes('N06Jrz5hx6Q9bcVDBBUrF3GKSTp2'));
it returns true.
The object with said Id exists. I checked the ids manually. I tried this:
console.log(reportIds.includes(['8VbBNBDrT1Z3kmyaQzy6LqskcOT2', 'N06Jrz5hx6Q9bcVDBBUrF3GKSTp2'].map(id => id)));
But this returned false.
Same with this:
console.log(reportIds.includes(['8VbBNBDrT1Z3kmyaQzy6LqskcOT2', 'N06Jrz5hx6Q9bcVDBBUrF3GKSTp2']));
So how can I check which ids are in the ids array?
You can use a combination of Array#filter and Array#includes for that :
let ids = [
"N06Jrz5hx6Q9bcVDBBUrF3GKSTp2",
"eLLfNlWLkTcImTRqrYnU0nWuu9P2"
];
let usersExamples = [
{
"id": "Nqez1dKRJ6aEpOb4BuUOK75iJoJ2"
},
{
"id": "SAlVGjXIagdDuJrHYO4i6LwzUql2"
},
{
"id": "eLLfNlWLkTcImTRqrYnU0nWuu9P2"
}
];
let result = usersExamples.filter(u => ids.includes(u.id));
console.log(result);
I have a JSON structure that looks like this:
"benefitValues" : [ {
"changeDate" : "2017-10-13T20:26:13.000+0000",
"changeUserName" : "aaaa",
"numericValue" : 20,
"value" : "20",
"amountType" : {
"allowCustomDataFlg" : false,
"dataType" : "Percent",
"defaultTypeFlg" : true,
"defaultValue" : "Unlimited",
"description" : null,
"maxValue" : null,
"minValue" : null,
"name" : "LIST",
"benefit" : {
"category" : "Facility Services",
"name" : "Single Limit",
"networkStatus" : "IN_NETWORK",
"planType" : "MedicalPlan",
"sortOrder" : 20,
"subcategory" : "Acupuncture Treatment",
"subcategorySortOrder" : 6
}
}
}]
Based on the string "Acupuncture Treatment", I need to extract the the value and the datatype. The dataset is very large, with hundreds of subcategories. I cannot find a good way to search through this data. I tried json-path and advanced-json-path, but if I do a search on a child element, there is no way for me to return the parents. I want my output to look like this:
{
"Subcategory" : "Acupuncture Treatment",
"Value" : "20",
"Type" : "Percent"
}
I was hoping there was an easy way to do this with an existing library, or at least with a simple loop.
This will find the matching element frombenefitValues, and transform the element into the format you're expecting:
var benefitValues = [{
"changeDate": "2017-10-13T20:26:13.000+0000",
"changeUserName": "aaaa",
"numericValue": 20,
"value": "20",
"amountType": {
"allowCustomDataFlg": false,
"dataType": "Percent",
"defaultTypeFlg": true,
"defaultValue": "Unlimited",
"description": null,
"maxValue": null,
"minValue": null,
"name": "LIST",
"benefit": {
"category": "Facility Services",
"name": "Single Limit",
"networkStatus": "IN_NETWORK",
"planType": "MedicalPlan",
"sortOrder": 20,
"subcategory": "Acupuncture Treatment",
"subcategorySortOrder": 6
}
}
}];
// Find the element
let treatment = benefitValues.find((item) => item.amountType.benefit.subcategory === 'Acupuncture Treatment');
let result = {
Value: treatment.value,
Subcategory: treatment.amountType.benefit.subcategory,
Type: treatment.amountType.dataType
}
console.log(result);
You can search through your data set and pull out only the items that match your string by using .filter. That would give you the entire object, so then you can use .map to transform it to the structure you want.
Or if you're only interested in the first result, you can use .find instead.
const json = {"benefitValues" : [{
"changeDate" : "2017-10-13T20:26:13.000+0000",
"changeUserName" : "aaaa",
"numericValue" : 20,
"value" : "20",
"amountType" : {
"allowCustomDataFlg" : false,
"dataType" : "Percent",
"defaultTypeFlg" : true,
"defaultValue" : "Unlimited",
"description" : null,
"maxValue" : null,
"minValue" : null,
"name" : "LIST",
"benefit" : {
"category" : "Facility Services",
"name" : "Single Limit",
"networkStatus" : "IN_NETWORK",
"planType" : "MedicalPlan",
"sortOrder" : 20,
"subcategory" : "Acupuncture Treatment",
"subcategorySortOrder" : 6
}
}
}]};
// With filter/map
const result = json.benefitValues
.filter(val => val.amountType.benefit.subcategory === "Acupuncture Treatment")
.map(val => ({Subcategory: val.amountType.benefit.subcategory, Value: val.value, Type: val.amountType.dataType}));
console.log(result)
// With find / manual transform:
const singleFullResult = json.benefitValues
.find(val => val.amountType.benefit.subcategory === "Acupuncture Treatment")
const singleResult = {
Subcategory: singleFullResult.amountType.benefit.subcategory,
Value: singleFullResult.value,
Type: singleFullResult.amountType.dataType
}
console.log(singleResult)
You can use Array.prototype.filter() combined with Array.prototype.map() and create an array of object with the structure you need. Here's an example:
let myArray = [{
"changeDate": "2017-10-13T20:26:13.000+0000",
"changeUserName": "aaaa",
"numericValue": 20,
"value": "20",
"amountType": {
"allowCustomDataFlg": false,
"dataType": "Percent",
"defaultTypeFlg": true,
"defaultValue": "Unlimited",
"description": null,
"maxValue": null,
"minValue": null,
"name": "LIST",
"benefit": {
"category": "Facility Services",
"name": "Single Limit",
"networkStatus": "IN_NETWORK",
"planType": "MedicalPlan",
"sortOrder": 20,
"subcategory": "Acupuncture Treatment",
"subcategorySortOrder": 6
}
}
}];
let ret = myArray
.filter(arr => arr.amountType.benefit.subcategory === 'Acupuncture Treatment')
.map(arr => {
return {
Subcategory: arr.amountType.benefit.subcategory,
Value: arr.value,
Type: arr.amountType.dataType
};
});
console.log(ret);
First the filter function will filter your array and return only the items related to 'Acupuncture Treatment', then the map function, that receives as a parameter a function that will be executed for each item inside the array and it will return a new structure, will return only the fields you need.
I have been playing around with the Angular UI Tree drag and drop and have come by an issue that has stumped me. The json is being received from my services. When it is received by my controller, I must format it properly with an empty array so it will be able to hold childen:
Formatting:
function categorySuccessPost(data) {
var emptyCategoryArray = {
Categories: []
}
for (var i = 0; i < data.length; i++) {
$.extend(data[i], emptyCategoryArray);
}
$scope.categoryData = data;
}
It is now formatted and looks like:
[ { "CategoryId": 27054, "MerchantId": 5594, "ProductCategoryId": 1310,
"Name": "BulkUpload", "Description": "BulkUpload", "DateCreated":
"/Date(1446793200000-0000)/", "IsActive": true, "IsDefault": false, "ItemCount":
5, "ResponseStatus": { "ErrorCode": "SUCCESS" }, "TotalRecordCount": 15,
"Categories": [] }, { "CategoryId": 23267, "MerchantId": 5594,
"ProductCategoryId": 818, "Name": "Coupon", "Description": "Coupon",
"DateCreated": "/Date(-62135596800000-0000)/", "IsActive": true, "IsDefault":
true, "ItemCount": 1, "ResponseStatus": { "ErrorCode": "SUCCESS" },
"TotalRecordCount": 15, "Categories": [] } }
I have tried two different functions when attempting to add a child:
Function 1 (Uses model value):
$scope.newSubItem = function (scope) {
var currentCategoryData = scope.$modelValue;
currentCategoryData.Categories.push({
CategoryId: currentCategoryData.CategoryId * 10 + currentCategoryData.Categories.length,
Name: currentCategoryData.Name + '.' + (currentCategoryData.Categories.length + 1),
Categories: []
});
};
Function 2 (Uses index of object in the array, and yes, I have made sure the correct index is being passed):
$scope.newSubItem = function (index) {
var array = $scope.categoryData;
array[index].Categories.push({
CategoryId: 12312,
Name: 'test',
Categories: []
});
};
The issue is that instead of pushing the new data to the selected index, it adds the json to every Categories :
[ { "CategoryId": 27054, "MerchantId": 5594, "ProductCategoryId": 1310,
"Name": "BulkUpload", "Description": "BulkUpload", "DateCreated":
"/Date(1446793200000-0000)/", "IsActive": true, "IsDefault": false, "ItemCount":
5, "ResponseStatus": { "ErrorCode": "SUCCESS" }, "TotalRecordCount": 15,
"Categories": [ { "CategoryId": 12312, "Name": "test", "Categories": [] } ] }, {
"CategoryId": 23267, "MerchantId": 5594, "ProductCategoryId": 818, "Name": "Coupon", "Description": "Coupon", "DateCreated": "/Date(-62135596800000-
0000)/", "IsActive": true, "IsDefault": true, "ItemCount": 1, "ResponseStatus":
{ "ErrorCode": "SUCCESS" }, "TotalRecordCount": 15, "Categories": [ {
"CategoryId": 12312, "Name": "test", "Categories": [] } ] }
I am not showing the HTML because it does not appear to be an issue. Here's where I have narrowed it down to, but still have no explanation:
If I use the data that goes through the $.extend method then it adds a child to every parent. But if I copy the json that is generated after the formatting, put it into and object and then read from that, then it only adds a child to the selected parent like I want. But it is necessary to add the empty array. Any idea why this is happening and any solution?
EDIT
One more piece of information that may be important: When I add a full Category (different function), rather than adding a subcategory and then try to add a child to the newly generated category then it works correctly (adding only a child to that category):
$scope.addCategory = function () {
var name = $scope.categoryName;
// Temporary
var categoryId = Math.floor((Math.random() * 50000) + 1)
console.log(name, categoryId)
$scope.categoryData.unshift({ CategoryId: categoryId, Name: name, Categories: [] })
$scope.categoryName = "";
$("#addCategoryModal").modal('hide');
Notification.success({ message: 'Category Added Successfully!', delay: 3000 });
}
I'm still not sure exactly why this is happening, but this was my solution to fixing the issue:
Remove the $.extend for loop and $.extend function:
function categorySuccessPost(data) {
$scope.categoryData = data;
}
When adding an item, check if the array has been initialized, if not, create it in the current scope:
$scope.newSubItem = function (scope) {
var currentCategoryData = scope.$modelValue;
if(currentCategoryData.Categories === 'undefined'){
currentCategoryData.Categories = [];
}
currentCategoryData.Categories.push({
CategoryId: currentCategoryData.CategoryId * 10 + currentCategoryData.Categories.length,
Name: currentCategoryData.Name + '.' + (currentCategoryData.Categories.length + 1),
Categories: []
});
};
The issue with this method is that you can no longer drag a node into an empty parent.