Transform a nested array of objects into a property template object with nested properties

I am in need of converting an array of objects into a nested property template object. The nested object will be constructed based on the checked items from the array.

Initially, the first level objects have their 'checked' key as null, implying that they will be included at the beginning of the property template object.

If the first level objects do not have any properties or none of the properties are marked as checked, the output should resemble this:

{staff: true}

However, if the objects contain properties and some of them are checked, the output structure will look like this:

{staffedLocation: ['schedulingGroup',
                   {property: 'staff', subProperties: ['description']}
                  ]
}

This is just a basic example, and sometimes the array of nested objects can go even deeper, necessitating the use of a recursive function. I'm struggling with how to implement recursion when the structure of the first level object differs from the rest.

An example of the array of objects being worked with is shown below:

[
    {checked: null, name: "staffedLocation", properties: [
        {checked: null, name: "oid", properties: null, toggle: null, type: "integer"},
        {checked: null, name: "_class", properties: null, toggle: null, type: "string"},
        {checked: true, name: "schedulingGroups", properties: null, toggle: null, type: "list"},
        {checked: null, name: "staff", properties: [
            {checked: null, name: "oid", properties: null, toggle: null, type: "integer"},
            {checked: null, name: "_class", properties: null, toggle: null, type: "string"},
            {checked: true, name: "description", properties: null, toggle: null, type: "string"},
            {checked: null, name: "limits", properties: null, toggle: null, type: "list"},
            {checked: null, name: "weeklyMaxHours", properties: null, toggle: null, type: "integer"}

        ], toggle: true, type: "list"},
    ], toggle: true, type: "staffedLocation"},
    {checked: null, 
    name: "staff", properties: [
        {checked: null, name: "oid", properties: null, toggle: null, type: "integer"},
        {checked: null, name: "_class", properties: null, toggle: null, type: "string"},
        {checked: null, name: "description", properties: null, toggle: null, type: "string"},
        {checked: null, name: "limits", properties: null, toggle: null, type: "list"},
        {checked: null, name: "weeklyMaxHours", properties: null, toggle: null, type: "integer"}
    ], toggle: true, type: "staff"},
    {checked: null, name: "assignedShifts", properties: null, toggle: null, type: "shiftForEmail"},
    {checked: null, name: "editedShifts", properties: null, toggle: null, type: "shiftForEmail"},
    {checked: null, name: "deletedShifts", properties: null, toggle: null, type: "shiftForEmail"},
    {checked: null, name: "unassignedShifts", properties: null, toggle: null, type: "shiftForEmail"},
    {checked: null, name: "rangeStart", properties: null, toggle: null, type: "timestamp"},
    {checked: null, name: "rangeEnd", properties: null, toggle: null, type: "timestamp"}
]

The desired output should be a nested object structured like this:

{   
    staffedLocation: ['schedulingGroup',{property: 'staff',subProperties: ['description']}],
    staff: true,
    assignedShifts: true,
    editedShifts: true,
    deletedShifts: true,
    unassignedShifts: true,
    rangeStart: true,
    rangeEnd: true
}

Answer №1

If you wish to implement your recursive function properly, make sure to apply it only to the properties within the topmost object rather than the object itself:

// Without ES6 syntax
function convert(content) {

function convertValues(props) {
    if (!(props && props.length && props.length > 0)) {
        return true;
    }
    var convertedProps = [];

    props.forEach(function(prop) {
       // Utilizing recursion
       var values = convertValues(prop.properties);
       if (prop.checked || values.length) {

           convertedProps.push(prop.name, values);
       }
    });

    return convertedProps;
}

var convertedContent = {};

content.forEach(function(obj) {
    convertedContent[obj.name] = convertValues(obj.properties);
});

return convertedContent;

}

The code provided may not be a perfect fit for your requirements, but I hope it can offer some guidance in the right direction.

Answer №2

Thanks to the assistance of Alexey, I was able to successfully transform everything as needed. The function found below now carries out the conversion process correctly.

$scope.convertToPropertyTemplate = function(content) {
    function convertValues(props) {

        if (!(props && props.length && props.length > 0)) {
            return true;
        }
        var convertedProps = [];

        props.forEach(function(prop) {
            // Recursive
            var convertedObj = {};
            var values = convertValues(prop.properties);
            if (prop.checked) {
                convertedProps.push(prop.name);
            } 

            if (values.length){
                convertedObj["property"] = prop.name;
                convertedObj["subProperties"] = values;
                convertedProps.push(convertedObj);
            }
        });

        return convertedProps;
    }

    $scope.convertedContent = {};

    content.forEach(function(obj) {
        $scope.convertedContent[obj.name] = convertValues(obj.properties);
    });
}

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

Implementing Various Conditions in ng-if Using AngularJS

I have a scenario in my AngularJS application where I need to display different buttons based on the value of type. If type === 'await_otp', then I should display two buttons (resend OTP and cancel), if type === 'submitted', then only t ...

Adapting a Function to Utilize a Passed Variable in an Angular 2 Application with Observables

I have implemented observables to fetch data in my Angular 2 application. Currently, multiple services/components are performing similar tasks. Therefore, I am looking to refactor the code to make it more efficient by passing a single parameter that varies ...

Is it possible to transmit form data via a JSON field when making a POST request to an API?

{ name:"ancient", logo:the image should be included here as form data, fimes:[{a:"ddsd","dd",},{a:'dfd'} } This particular JSON dataset needs to be uploaded to the server. The logo field has to contain an image. ...

A custom JavaScript function designed to facilitate the downloading of a file that includes the user's input directly to the user

Is there a way to use javascript to generate a file based on user input and provide it as a download without storing it on the server? For instance, imagine a scenario where a user is using an application and they want to download their work by clicking ...

$watchCollection not firing when object is modified

I've been trying to understand why the watchCollection function is not triggering on object changes. .factory('Products', function($http, $timeout){ function Products(data){ if (data) { this.setData(data); ...

Using a single function for multiple IDs in JavaScript

function increment(value) { var txtNumber = document.getElementById(value); var newNumber = parseInt(txtNumber.value) + 1; txtNumber.value = newNumber; } function decrement(value) { var txtNumber = document.getElementById(value); var newNumber = ...

The correlation of unclickable and unmovable elements in the Firefox browser

I have been working on implementing tab close functionality in Bootstrap using an <a> element that includes the tab title text along with a close icon displayed as a background image within a span. In order to ensure smooth operation, it is essentia ...

Having trouble retrieving a hidden value in JavaScript when dealing with multiple records in a Coldfusion table

In this table, there is a column that allows users to select a predicted time. <cfoutput query="getReservations"> <tbody> <td><input class="form-control predicted" name="predicted" id="ReservaTempoPrevisto" placeholder= ...

Tips for utilizing a .node file efficiently

While attempting to install node_mouse, I noticed that in my node modules folder there was a .node file extension instead of the usual .js file. How can I execute node_mouse with this file format? After some research, it seems like node_mouse may be an a ...

Is it possible to convert a list of MongoDB documents into a tabular format?

What is the best way to convert a list of MongoDB documents into a tabular format? For example: Given the following list of BsonDocuments [0] = { "_id" : ObjectId("546ce80d43f5c2b7d8a713bd"), "Address" : "61- A, Pocket- C, Ram Vihar Phase II, UP", "Pinc ...

Containers shared among Next.js pages within a folder

Is it possible to have a shared container for all pages within a specific folder in NextJS? One potential solution could involve the following code: // pages/folder/index.js export default function Container({ children }) { return <Container>{ch ...

Utilize Bootstrap 3 Datepicker version 4 to easily set the date using Moment.js or Date objects

I'm currently utilizing the Within my project, I have a datetime picker labeled as dtpFrom <div class='input-group date ' id='dtpFrom'> <input type='text' class="form-control" /> <span c ...

What is the best method for extracting an attribute value from an HTML <a> element?

I've been attempting to scrape the specified website, but I'm having trouble retrieving the value of the 'data-link' attribute. Is there anyone who can assist me with this issue? //first try (resulting in an error) const puppeteer = ...

Why isn't my state updating with componentDidMount()?

I am currently exploring React and working on creating a view counter for different divs. To achieve this, I require the height and scroll top height of the divs. However, after obtaining these values, I am facing issues when trying to set state with the ...

Error occurred when trying to run 'npm run dev' on vite: Unable to access the file "node_modules/react/jsx-dev-runtime.js"

After successfully creating a Vite app, I encountered three errors when trying to run the app with npm run dev: [ERROR] Cannot read file "node_modules/react/jsx-dev-runtime.js": Access is denied. [ERROR] Cannot read file "node_modules/react/index.js": Acc ...

Exploring the magic of the (!!!) operator in JavaScript!

The !! operator proves to be quite helpful when converting non-boolean data types into Boolean values, mainly for "True" conditions. However, when it comes to false conditions, is using !!! necessary? ...

Tips on skipping the need to repeatedly use `@ApiProperty()` for every dto in NestJs-swagger

I'm currently exploring ways to streamline the process of specifying @ApiProperty() for each DTO. I've heard about a method involving the creation of a nest-cli.json file, where if you define Promise<DTO> in your controller within nest-swa ...

Get the child from Firebase using the $id parameter in the $routeParams

My objective is to utilize the URL for passing data from my list to the detail view while containing the Firebase id. Although I successfully retrieved the id, I am struggling to read the associated record in Firebase. Specifically, I have a collection of ...

Adding a specific element to an array using JQuery

I am in the process of developing a web application using jQuery to track goals and habits. Users can set a main goal such as 'Discipline' and then add sub-goals or habits related to that main goal (e.g. 'exercise every day'). Organizi ...

I have successfully stored an array in session storage and was able to retrieve it. While I am able to access the data, I am unable to duplicate the array

let data=[ { "id":1, "name":"Dashboard", "status":0 }, { "id":2, "name":"Facility", "status":0 }] The above code snippet shows the original data. Next, I am storing this data using session storage as shown below--- $window.sessionStorage.setItem("userIte ...