My application is MVC 5, I am using the following Ajax to generate an array:
$.ajax({
type: "Post",
url: '@Url.Action("Getthereport", "Surveys")',
async: false,
cache: false,
dataType: "json",
data: { 'test': "All" },
success: function (result) {
if (result && result.Grid.length > 0) {
for (let i = 0; i < result.Grid.length; i ) {
jsonData.push({
Question: result.Grid[i].Body,
QuestionId: result.Grid[i].QuestionId,
myData: { name: result.Grid[i].name, value: result.Grid[i].value }
});
};
}
},
complete: function () {
reduce();
},
error: function(err) {
alert(err.status " : " err.statusText);
}
});
I generates the following:
var jsonData = [
{
Question: "Was the training useful?",
QuestionId: 1,
myData: [{ name: 'No', value: 1 }] },
{
Question: "Was the training useful?",
QuestionId: 1 ,
myData: [{ name: 'Yes', value: 1 }]
}];
to merge the objects, I use:
const result = Object.values(jsonData.reduce((acc, obj) => {
if (!acc[obj.QuestionId]) {
acc[obj.QuestionId] = obj;
} else {
acc[obj.QuestionId].myData = acc[obj.QuestionId].myData.concat(obj.myData);
}
return acc;
Works great if the array is hardcoded and generates:
var jsonData = [
{
Question: "Was the training useful?",
QuestionId: 1,
myData: [{ name: 'No', value: 1 },
{ name: 'Yes', value: 1 }]
}];
However, if the array is generated by Ajax call, I get the following error:
acc[obj.QuestionId].myData.concat is not a function
I tried to run the reduce script on Ajax complete and directly both did not work.
CodePudding user response:
In the success
property of your ajax
call options you're pushing myData
as an object, not as an array
success: function (result) {
if (result && result.Grid.length > 0) {
for (let i = 0; i < result.Grid.length; i ) {
jsonData.push({
Question: result.Grid[i].Body,
QuestionId: result.Grid[i].QuestionId,
myData: { name: result.Grid[i].name, value: result.Grid[i].value }
});
};
}
},
Which means that the output is not as you stated but rather
var jsonData = [
{
Question: "Was the training useful?",
QuestionId: 1,
myData: { name: 'No', value: 1 } //<-- Objects not arrays
},
{
Question: "Was the training useful?",
QuestionId: 1,
myData: { name: 'Yes', value: 1 }
}
];
You can either declare it as an array at that stage to generate the output you originally posted,
for (let i = 0; i < result.Grid.length; i ) {
jsonData.push({
...
myData: [{ name: result.Grid[i].name, value: result.Grid[i].value }]
});
};
or adjust your reduce.
var jsonData = [
{
Question: "Was the training useful?",
QuestionId: 1,
myData: { name: 'No', value: 1 }
},
{
Question: "Was the training useful?",
QuestionId: 1,
myData: { name: 'Yes', value: 1 }
}
];
const result = Object.values(jsonData.reduce((acc, obj) => {
acc[obj.QuestionId] ??= { ...obj, myData: [] };
acc[obj.QuestionId].myData.push(obj.myData);
return acc;
}, {}));
console.log(JSON.stringify(result, null, 2))