Exploring various layers of nested data

I am currently developing a comprehensive global data storage system for my application (specifically an Angular JS app - although this question pertains to JavaScript in general).

I have established a 'service' that is responsible for setting the data, retrieving the data, and other related functions.

Here is how it looks:

angular.module('core').factory('dataService', function(callsService) {
  let properties = {
    globalData: {}
  };

  properties.insertData = function(data) {
    for (let x in data) {
      this.globalData[x] = data[x];
    }
    return;
  }

  properties.getData = function(data) {
    return this.globalData[data];
  }

  return properties;
});

The usage of the service would be like this:

dataService.insertData({foo: 'bar'});
dataService.getData('foo'); // 'bar'

However, issues arise when dealing with nested data structures, for example:

dataService.insertData({foo: {bar: 'hello world'}});
dataService.getData('foo'); // {bar: 'hello world'}

While this behavior is expected due to object references, how can I achieve something like:

dataService.getData('foo.bar'); // 'hello world'

or

dataService.getData('[foo][bar]'); // 'hello world'

When revisiting my 'properties.getData' method, is there a way to recursively access nested objects or employ another technique?

properties.getData = function(data) {
  return this.globalData[data]; // should be able to retrieve nested objects
}

Answer №1

New Answer:

This concise recursive function is designed to meet your specific requirements:

retrieveData = (args, data) => args.length ? this.getData(args.slice(1), data ? data[args[0]] : this.globalData[args[0]]) : data ? data : this.globalData

Simply provide an array of property arguments or array indices to fetch the desired value:

dataService.retrieveData(['arrayOfData', 2, 'propOnArrElement', 'subProp', 'desiredValue'])

Explanation:

The function's signature looks like this:

getData(args: Array, data?: any): any
,

With the following characteristics:

  1. It expects an Array as the first argument (containing the path to the nested data)
  2. An optional second argument represents the data structure being queried (either an Object or Array)
  3. The function returns the requested data in any format.

Functionality Overview:

Upon invocation,

  • Ensure no definition for the second argument, allowing access to the globalData object.
  • Check the length of the args Array (args.length ?),
    • If elements exist, initiate a recursive call (this.getData(),
      • Omit the first arg from args Array (args.slice(1),),
      • Reintroduce the data argument if applicable (data ?).
        • Accessible properties/indices are identified on the data Object/Array using the first arg element in the latest recursive call (data[args[0]] :),
        • In instances where it remains undefined (initial function call), utilize the globalData property instead (this.globalData[args[0]])).
    • Through further recursion, the data structure narrows to deeper levels while args list diminishes.
      • Once args length evaluates to false (exhausted exploration!), the function merely returns the current data object (: data ? data).
      • For calls with an empty array, the entire globalData will be returned instead (: this.globalData).

I trust you find this helpful or engaging to read. It was quite satisfying when this solution emerged while showering tonight. :P

Bonus Content:

An alternative method utilizing ES6 rest parameters and Array.reduce goes even further (enabling function calling without passing an array):

retrieveData = (...args) => args.reduce((data, arg) => data[arg], this.globalData)

Invocation example:

dataService.retrieveData('firstarg', 'secondarg', 'onemorearg', 'desireddata')

Initial Discouraging Response:

To directly fetch the data property, simply access it during function invocation:

const result = dataService.getData(‘foo’).bar

Alternatively:

const result = dataService.getData(‘foo’)[‘bar’]

Answer №2

It seems like you're asking two questions at once.

To address your first query about passing something similar to dataService.getData('foo.bar');

You have the ability to access object properties using strings in this manner:

var property = foo['bar'];

If desired, you can make this recursive like so:

var property = foo['bar']['baz'];

As for your second question, it might be related to another discussion found at this link?

Answer №3

Utilize the $parse service:

  var object = { 'a': [{ 'b': { 'c': 3 } }] };
  var accessor= 'a[0].b.c';

  var result = $parse(accessor)(object);
  console.log("result =>",result);

  // Output: 3 

A Sneak Peek at The DEMO

angular.module("app",[])
.run(function($parse) {

  var object = { 'a': [{ 'b': { 'c': 3 } }] };
  var accessor= 'a[0].b.c';
  
  var result = $parse(accessor)(object);
  console.log("result =>",result);
  
  // Output: 3 
})
 <script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app">
</body>

For further details, check out AngularJS $parse Service API Reference.

Answer №4

In my opinion, using an arrow function as a selector would be beneficial. Here is how you can implement it:

dataService.getData(storage => storage.foo.bar);

The corresponding function in your service should look like this:

properties.getData = function (dataSelector) {
    return dataSelector(this.globalData);
} 

Here is a practical example to demonstrate how it works:

const data = {
  prop1: {
    prop2: 1
  }
};

function getData(dataSelector) {
  return dataSelector(data);
}

const prop2 = getData(data => data.prop1.prop2);

console.log(prop2);

If you prefer not to use arrow functions as selectors, you could also use regex to split the string. Here's an alternative approach:

properties.getData = function(data) {  
  var props = data.replace(/\]/g,'').split(/\.\[/g);

 return props.reduce((obj, prop) => obj[prop], this.globalData);

} 

For more information, you may find this article helpful.

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

Triggering transitionend event once with an added if condition

Currently, I have an application of an if statement that examines whether an element contains a style attribute. In the event that the style attribute is absent, it appends inline styling. Conversely, if the style attribute exists, it is removed. Furthermo ...

Having trouble with the post request in Express JS and Vue? Don't worry, we've got you covered

I've been following a tutorial to set up a basic app and everything is working smoothly, except for the post request which seems to be causing me trouble. Tutorial: https://www.youtube.com/watch?v=HkIGAqAP1GY Although the issue is reproducible based ...

Resolution for Vue3: Understanding why a component instance's template ref cannot locate a defined function

LoginInfo.vue <script setup lang="ts"> import { rules } from './config/AccountConfig' import { reactive } from 'vue' import { ref } from 'vue'; import { ElForm } from 'element-plus'; const info = reac ...

What is the reason for the request to accept */* when the browser is seeking a JavaScript file?

The html source appears as follows: <script type="text/javascript" language="JavaScript" src="myscript.js"></script> Upon debugging the http request using Fiddler, it is evident that the browser (Chrome) sends a GET request for myscript.js wi ...

Issue with Vue2's v-text functionality

Recently, I've delved into Vue2 and encountered a problem with form submission and validation on a single page. The issue lies in the error display process – I want errors to be shown beneath each form input as soon as they occur, rather than waitin ...

Error in Access-Control-Allow-Origin when using Node.js and JSONP

It seems like JSONP eliminates cross domain restrictions. I am currently attempting to create a JSONP service with node and express. Below is a simple example of the code: self.routes['/portfolio'] = function(req, res) { // Website you wis ...

The Express middleware type cannot be assigned as expected

I'm encountering an error where my first middleware is being red underlined. I can't figure out why it's only happening to the first one. Can anyone provide some guidance on this issue? I'm still quite new to TypeScript. Did I overloo ...

Retrieving Information from Ajax Call Using Python

I am struggling to figure out how to retrieve data from an Ajax request in my JavaScript code within a Python Flask application. The Ajax request I am working with does not involve jQuery. I have attempted using request.form.get() and request.get_json() i ...

The process of enabling NPM packages for use with ES6 and ECMAScript

Currently, I am working on developing an NPM package using TypeScript. My main concern is how to ensure that this package can be made available for both ES and Node modules. To achieve this, I have configured Rollup along with a few settings: rollup.conf ...

Nextjs couldn't locate the requested page

After creating a new Next.js application, I haven't made any changes to the code yet. However, when I try to run "npm run dev," it shows me the message "ready started server on [::]:3000, url: http://localhost:3000." But when I attempt to access it, I ...

Having trouble accessing session value within an AngularJS file

Is there a recommended method for accessing session values from an angularjs file that's written in asp.net(C#)? I attempted to use the following code but was unsuccessful: $session.get(key) ...

Unable to update the React state on a component that is unmounted when using HOOK

I'm currently working on a user authentication code in React, specifically for an Expo project. function App(){ const [user, setUser] = useState(null); if (user){ return <Dashboard user={user} /> } return <Authentication ...

The Vue.js modal is unable to resize below the width of its containing element

My challenge is to implement the Vue.js modal example in a larger size. I adjusted the "modal-container" class to be 500px wide, with 30px padding and a max-width of 80%. However, I'm facing an issue where the "modal-mask" class, containing the contai ...

JavaScript: Harnessing the power of scripts to handle dynamically loaded data via AJAX

I am currently working on a webpage where I need to display various events using AJAX and PHP. One requirement is that when a user clicks on the "view event" link at the bottom of each event, a modal window should pop up. To achieve this functionality, I h ...

Modifying attributes for individual components in Vue.js classes

Recently, I integrated a reusable component called "LightBox" into my website, which displays images in higher resolution. The LightBox functionality is linked to each element having a thumbnail. However, I encountered an issue. There are multiple elements ...

Which API is utilized by duojs for its JavaScript modules?

I am currently utilizing duojs, a front-end web development tool similar to browserify or component. With duojs, you can directly import css and js from the file itself without any external package manifests. While I'm trying to figure out how to wri ...

Verify if a <select> element exists inside the main div

Is there a way for me to check if a <select> element is present within the parent div and display certain content based on its existence? Appreciate any assistance! ...

"Encountering a restricted URI error when attempting to load a text file using AJAX

After reviewing the recommended link, I found myself struggling to grasp the suggestion to "Use Greasemonkey to modify Pages and start writing some javascript to modify a web page." Currently, I am encountering an error when loading a text file using $.aj ...

Error in Cross-Origin Resource Sharing (CORS) encountered when trying to

Below is the code snippet provided: app.js: const passport = require('passport') , FacebookStrategy = require('passport-facebook').Strategy , ... passport.serializeUser(function(user, done) { console.log('serializing user&a ...

Saving data to a database using jQuery Ajax when multiple checkboxes are checked

Looking for a solution to store checkbox values into a database using jQuery Ajax to PHP. To see a live demo, click here. The image above illustrates that upon checking certain checkboxes and clicking Update, the checkbox values along with their IDs will ...