i am trying to load this json in my page but foreach break and gives error as the number is not in serial
if we provide the number in serial it works. serial means in incremental this is my json
{
"": {
"id": "",
"name": "",
"reply": "",
"parent": "",
"actions": []
},
"0": {
"id": "0",
"name": "",
"reply": "",
"parent": "",
"actions": [
"01",
"02",
"03",
"04",
"06",
"07"
]
},
"01": {
"id": "01",
"name": "Order Status",
"reply": "Please provide your order number",
"parent": "0",
"actions": [
"011"
]
},
"07": {
"id": "07",
"name": "Book Appointment",
"reply": "Book Appoinme",
"parent": "0",
"actions": []
},
"welcomeMssg": "Do you need help with :-",
"startId": "0",
"scName": "test name"
}
and this is my javascript
var scenario = "";
var fdata = null;
function getScenarioData(scid, cid) {
scenario = scid;
var obj = {
client: cid,
scenario: scid,
};
$.ajax({
type: "GET",
url: "getdata.php",
data: obj,
success: function (data) {
data = JSON.parse(data);
fdata = data;
console.log(fdata);
document.getElementById("welcomeMessage").value = data.welcomeMssg;
document.getElementById("scenarioName").value = data.scName;
scenarioName = data.scName;
welcomeMessage = data.welcomeMssg;
start = data.startId;
buttons = data;
document.getElementById("main1").style.display = "block";
document.getElementById("entry").style.display = "none";
ac = buttons[start].actions;
for(let k in buttons) {
if(buttons[k].actions){
count[k] = buttons[k].actions.length 1;
}
}
console.log(count);
ac.forEach(e => {
var input = document.createElement("input");
input.type = "text";
input.className = "replybox m-1 p-2 form-control";
input.placeholder = "reply";
input.style.display = "inline";
input.value = buttons[e].name;
input.id = buttons[e].id;
var id = buttons[e].id;
input.onclick = function () {
addRes(id, buttons[e].parent);
};
// input.onkeyup = function () {
input.onchange = function () {
buttons[id].name = document.getElementById(id).value;
if (document.getElementById("show" id)) {
document.getElementById("show" id).innerHTML =
"(for " document.getElementById(id).value ")";
}
};
var d = document.createElement("div");
var s = document.createElement("span");
d.id = "reply" id;
s.innerHTML = `<i class='fa fa-times-circle circle' aria-hidden='true' onclick='deleteButton("${id}");' style='font-size:15px;cursor:pointer;margin-left:-10px;;'></i>`;
d.appendChild(input);
d.appendChild(s);
document.getElementById("replies0").appendChild(d);
});
},
error: function (e) {
console.log(e.message);
},
});
}
if i change the json output to 2 instead of 7 it works fine. i am confused is it mandatory to have data in incremental if we are using foreach
when i say if i replace 7 with 2 means this
"07": {
"id": "07",
"name": "Book Appointment",
"reply": "Book Appoinme",
"parent": "0",
"actions": []
},
here is live site for demo https://way2enjoy.com/shopify/1/whatsapp-chat/bot/1/2/edit_scenario.php?client=50457
any help will be great
i get this error at console
Uncaught TypeError: Cannot read properties of undefined (reading 'name')
at edit_scenario.js:39
at Array.forEach (<anonymous>)
at Object.success (edit_scenario.js:33)
at c (jquery.min.js:2)
at Object.fireWith [as resolveWith] (jquery.min.js:2)
at l (jquery.min.js:2)
at XMLHttpRequest.<anonymous> (jquery.min.js:2)
CodePudding user response:
You are looping over ["01", "02", "03", "04", "06", "07"]
and try to access each of these keys on the returned object. Yet data["02"]
, data["03"]
, etc. do not exist, thus resulting in undefined
.
ac.forEach(e => { // … input.value = buttons[e].name; input.id = buttons[e].id; var id = buttons[e].id; input.onclick = function () { addRes(id, buttons[e].parent); }; // … });
In the above code ac
refers to buttons[start].actions
or simply put buttons["0"].actions
which is ["01", "02", "03", "04", "06", "07"]
.
You then start iterating over these actions, trying to use each element as key to access the object. buttons[e]
is buttons["01"]
, buttons["02"]
, etc. Since you only have the keys "01"
and "07"
present, all other attempts will result in undefined
.
This produces an error because buttons[e].name
-> buttons["02"].name
-> undefined.name
-> "Uncaught TypeError: Cannot read properties of undefined (reading 'name')".
This can be solved in three ways. Two of which are the responsibility of the server.
Client-side solution: Skip the elements if they are not present within the object.
// Only select the actions that are actually present in `buttons`. ac = buttons[start].actions.filter(e => e in buttons);
Or alternatively:
ac.forEach(e => { // Skip the iteration if `e` is not present in `buttons`. if (!(e in buttons)) return; // … });
Server-side solution 1: Send only the actions to the client that are actually present in the response.
{ // … "0": { "id": "0", "name": "", "reply": "", "parent": "", "actions": ["01", "07"] }, // … }
Server-side solution 2: Instead of reducing the actions you could also send all the related objects.
{ // … "0": { // … "actions": ["01", "02", "03", "04", "06", "07"] }, "01": { /* … */ }, "02": { /* … */ }, "03": { /* … */ }, "04": { /* … */ }, "05": { /* … */ }, "06": { /* … */ }, "07": { /* … */ }, // … }