What is the most effective way to access nested elements by index in JavaScript?

I am looking to design a user-friendly form that presents questions for users to navigate, revealing different answers/questions based on their responses. For example:

var json = 
     {
      "Did you restart the computer?": [
        {
          "Yes": [
            {
              "Is the software running?": [
                {
                  "Yes": "Cannot help",
                  "No": "Open it"
                }
              ]
            }
          ],
          "No": "Please restart it"
        }
      ]
    }

Is there a more efficient data structure than accessing options by keys like json["Did you restart the computer?"][0]["Yes"] and json["Did you restart the computer?"][0]["No"]?

If a user selects "Yes" for the first question, I know I can access keys like this:

Object.keys(json["Did you restart the computer?"][0]["Yes"][0])
>> ['Is the software running?']

And if they select "Yes" again:

Object.keys(json["Did you restart the computer?"][0]["Yes"][0]["Is the software connected to the server?"][0])
>> (2) ['Yes', 'No']

However, this method seems complex. Is there a simpler way to access keys/values using indexes (e.g., json[0][0][1])?

Answer №1

Based on Bergi's feedback, there is no need for arrays; instead, simply utilize "Yes" and "No" as keys

document.addEventListener('DOMContentLoaded', () => {
  const questionElement = document.getElementById('question');
  const yesBtn = document.getElementById('yesBtn');
  const noBtn = document.getElementById('noBtn');

  let currentStep = paths;

  const updateQuestion = () => {
    const isFinalAnswer = typeof currentStep === 'string';
    questionElement.innerHTML = isFinalAnswer ? currentStep : Object.keys(currentStep)[0];
    yesBtn.hidden = isFinalAnswer;
    noBtn.hidden = isFinalAnswer;
  };

  document.getElementById('container').addEventListener('click', (e) => {
    if (e.target.id === 'yesBtn' || e.target.id === 'noBtn') {
      const response = e.target.id === 'yesBtn' ? 'Yes' : 'No';
      const question = Object.keys(currentStep)[0];

      if (currentStep[question] && currentStep[question][response]) {
        currentStep = currentStep[question][response];
        updateQuestion();
      }
    }
  });

  updateQuestion();
});
#container {
  text-align: center;
  margin-top: 50px;
}

#question {
  margin-bottom: 20px;
}

.btn {
  margin: 5px;
  padding: 10px 20px;
  cursor: pointer;
}
<div id="container">
  <div id="question"></div>
  <button class="btn" id="yesBtn" hidden>Yes</button>
  <button class="btn" id="noBtn" hidden>No</button>
</div>

<script>
  const paths = {
    "Did you restart the computer?": {
      "Yes": {
        "Is the software running?": {
          "Yes": "Cannot help",
          "No": "Open it"
        }
      },
      "No": "Please restart it"
    }
  };
</script>

Prior solution:

document.addEventListener('DOMContentLoaded', () => {
  const questionElement = document.getElementById('question');

  let currentStep = paths[0]; // start

  const updateQuestion = () => {
    const isString = typeof currentStep === 'string';
    questionElement.innerHTML = isString ? currentStep : currentStep.question;
    yesBtn.hidden = isString;
    noBtn.hidden = isString;
  };

  document.getElementById('container').addEventListener('click', (e) => {
    const which = e.target.id === 'yesBtn' ? 0 : 1
    if (currentStep.answers && currentStep.answers[which]) {
      const next = currentStep.answers[which].next;    
      currentStep = Array.isArray(next) ? next[0] : next;
      updateQuestion();
    }
  });
  updateQuestion();
});
#container {
  text-align: center;
  margin-top: 50px;
}

#question {
  margin-bottom: 20px;
}

.btn {
  margin: 5px;
  padding: 10px 20px;
  cursor: pointer;
}
<div id="container">
  <div id="question"></div>
  <button class="btn" id="yesBtn" hidden>Yes</button>
  <button class="btn" id="noBtn" hidden>No</button>
</div>

<script>
  const paths = [{
    "question": "Did you restart the computer?",
    "answers": [{
        "response": "Yes",
        "next": [{
          "question": "Is the software running?",
          "answers": [{
              "response": "Yes",
              "next": "Cannot help"
            },
            {
              "response": "No",
              "next": "Open it"
            }
          ]
        }]
      },
      {
        "response": "No",
        "next": "Please restart it"
      }
    ]
  }];
</script>

Answer №2

In my opinion, this question may not be the best fit for StackOverflow due to potential subjective responses. In order to access objects by keys and utilize indexes effectively, it is recommended to use an array structure and avoid including text elements within your data structure. Consider structuring your data like the following example:

const options = [
  {
    type: "question",
    text: "Have you done this?",
    yes: {
      text: "Yes",
      options: [{
        type: "question",
         text: "Is the software running?",
         yes: {
           text: "Yes",
           options: [{
             type: "message",
             text: "Can't help",
           }]
         },
        no: {
          text: "No",
          options: [{
            type: "message",
            text: "Call for help",
          }]
        }
      }]
    },
    no: {
      type: "question",
      text: "No",
      options: [{
        type: "question",
        text: "have you tried this other thing?",
        options: [
          `...`
        ]
      }]
    }
  }
]

By accessing

options[0].yes.options[0].yes.options[0].text
, you will get Can't help.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for verifying conditional input fields in a React component?

As a beginner in React, I attempted to create a SignIn form component that dynamically changes its layout based on a boolean prop toggled between Login and Signup options. In the signup version, there is an additional text field labeled Confirm password, w ...

Issue encountered while attempting to load JSON data into Hive

JSON data structure is as follows: {"id":"U101", "name":"Rakesh", "place":{"city":"MUMBAI","state":"MAHARASHTRA"}, "age":20, "occupation":"STUDENT"} {"id":"","name":"Rakesh", "place":{"city":"MUMBAI","state":"MAHARASHTRA"}, "age":20, "occupation":"STUDENT ...

Tips for inserting information from a JSON file into a mailto hyperlink

As a newcomer to JavaScript, I am eager to tackle the challenge presented below: Situation: In possession of a JSON file containing personal details such as name, email address, bio, etc., my task is to design a basic web page showcasing this data for ea ...

When using the HTML5 input type time in Chrome and the value is set to 00:00:00, it may not be fully completed

After inputting the html code below <input id="time_in" type="time" step="1" name="duration"> and setting the value in the browser to "00:00:00", everything appears fine. However, upon inspecting the console or submitting the form, the value gets ...

The Facebook Comments feature on my React/Node.js app is only visible after the page is refreshed

I am struggling with getting the Facebook Comment widget to display in real-time on my React application. Currently, it only shows up when the page is refreshed, which is not ideal for user engagement. Is there a way to make it work through server-side r ...

Sharing Data Across Multiple Windows in Angular 2 Using a Singleton List

My multiplayer game involves adding new players to a single game room lobby, which is essentially a list of current players. How can I update this list for all connected players when new ones join? I implemented a service and included it in the providers ...

Utilize the grouping functionality provided by the Lodash module

I successfully utilized the lodash module to group my data, demonstrated in the code snippet below: export class DtoTransactionCategory { categoryName: String; totalPrice: number; } Using groupBy function: import { groupBy} from 'lodash&apo ...

Convert numbers to words in the Indian currency format as you type up to a 16-digit number, displaying the Indian rupees symbol automatically without the need to click a button

How can we modify the code below to automatically add the Indian rupees symbol in the input field? https://i.sstatic.net/TlNLc.png $('.allow_decimal').keyup(function (event) { $(this).val(function (index, value) { return valu ...

Extract JSON data from a third-party website using JavaScript

I'm facing a challenge parsing JSON from an external website using JavaScript or jQuery for a Chrome extension. Specifically, I need to extract the number from an external URL with the JSON {"_visitor_alertsUnread":"0"} and assign that number to a var ...

Fetching JSON and API data to populate Graphs for Android Application

I'm currently working on an Android app using Kotlin to track Covid-19 data. I've implemented retrofit to fetch the information from an API provided by CovidActNow.org, which requires an API key. However, when testing my app, the data is not bein ...

Is it possible to stop an AjaxBehaviorEvent listener or send extra information to the f:ajax onevent function?

In the controller, I have created a listener that looks something like this: public class FooController { public void doSomething(AjaxBehaviorEvent evt) { closeDialogFlag = true; .. if(!isValid){ closeDialogFlag = f ...

encountering difficulties with installing dependencies using yarn or npm

After cloning a repository, I attempted to install the dependencies using npm install or yarn but encountered the following errors: For Yarn: https://gyazo.com/2fdf52c4956df2e565cc0b1cedf24628 For npm install: https://gyazo.com/a1d197e9ead89dbe4a7d3c5b8f ...

Tips for maximizing the effectiveness of the .bind(this) method in Meteor js

Hey there, I've got a question for you. How do we go about using the bind method in Meteor? Take a look at this code snippet below. It feels like there's some repetition going on that bothers me. Thank you so much for sharing your thoughts! Bi ...

Top method for stacking several divs in a vertical line

In search of the most effective method for organizing numerous dynamically generated divs (all with identical widths) in a vertical stack, two potential solutions have emerged: Utilize float:left... Implement an unordered list and enclose each div within ...

display and conceal elements and refresh action

Can anyone help me with a function to hide and show a div? function toggledDivVisibility(divName) { if (divName.is(':hidden')) { var hiddenDiv = document.getElementById("filter"); hiddenDiv.style.display = 'block&a ...

Implementing context menus on the Material-UI DataGrid is a straightforward process that can enhance the user experience

I am looking to enhance my context menus to be more like what is demonstrated here: Currently, I have only been able to achieve something similar to this example: https://codesandbox.io/s/xenodochial-snow-pz1fr?file=/src/DataGridTest.tsx The contextmenu ...

Transferring data from client to server: Weighing the pros and cons of

When dealing with 1-5 variables on the client side that need to be sent to the server using AJAX (Post Method), there are two primary methods of getting them there. One option is to use JSON to encode and decode the variables, sending them as a JSON stri ...

My changes to the HTML file are not being reflected in the browser, even after clearing the cache. This is happening in an Angular and Node.js application

I'm currently developing an application using Angular and Node.js. I've noticed that when I make changes to the HTML file, the browser isn't updating even after clearing the cache. Could this be a coding issue? Any suggestions on how to fix ...

Stop the recurrence of multiple clicks by incorporating a Bootstrap modal popup confirmation

$('button[name="remove_levels"]').on('click', function (e) { var $form = $(this).closest('form'); e.preventDefault(); $('#confirm').modal({ backdrop: 'static', ...

Encountering the issue of receiving an undefined value for a variable despite having previously defined it within

I’ve been working on implementing the Google Maps distance matrix API with the google-distance-matrix library. Here’s the code snippet I’m using: app.get("/users", (req, res) => { // console.log(req.query); // res.send(req.query); ...