What is the best way to arrange groups in a specific order?

At the moment, the response sent back to the client-side appears in a specific structure:

[
  {
    "categoryName": "Orders",
    "categoryItems": [
      {
        "group": "Group B",
        "groupSettings": [
          {
            "settingName": "Group b description"
          }
        ]
      },
      {
        "group": "Group C",
        "groupSettings": [
          {
            "settingName": "Group c description"
          }
        ]
      },
      {
        "group": "Group A",
        "groupSettings": [
          {
            "settingName": "Group a description"
          }
        ]
      }
    ]
  },
  {
    "categoryName": "Notifications",
    "categoryItems": [
      {
        "group": "",
        "groupSettings": [
          {
            "settingName": "Notification setting"
          }
        ]
      }
    ]
  },
  {
    "categoryName": "Personalisation",
    "categoryItems": [
      {
        "group": "",
        "groupSettings": [
          {
            "settingName": "Personalisation setting"
          }
        ]
      }
    ]
  }
]

The desired layout, however, should be different:

[
  {
    "categoryName": "Personalisation",
    "categoryItems": [
      {
        "group": "",
        "groupSettings": [
          {
            "settingName": "Personalisation setting"
          }
        ]
      }
    ]
  },
  {
    "categoryName": "Notifications",
    "categoryItems": [
      {
        "group": "",
        "groupSettings": [
          {
            "settingName": "Notification setting"
          }
        ]
      }
    ]
  },
  {
    "categoryName": "Orders",
    "categoryItems": [
      {
        "group": "Group A",
        "groupSettings": [
          {
            "settingName": "Group a description"
          }
        ]
      },
      {
        "group": "Group B",
        "groupSettings": [
          {
            "settingName": "Group b description"
          }
        ]
      },
      {
        "group": "Group C",
        "groupSettings": [
            {
                "settingName": "Group c description"
              }
            ]
        }
    ]
  }
]

To sort the categoryName to match the expected order, I am considering using an array of objects with categoryName and sequence properties. However, I need help in implementing the sorting logic into my code.

This is my current code snippet:

const groupedData = _.chain(allData)
      .groupBy('sectionName')
      .map((allData, sectionName) => ({
        categoryName: sectionName,
        categorySettings: _.chain(allData)
          .groupBy('group')
          .map((groupSettings, group) => ({
            group: group,
            groupSettings: _.chain(groupSettings)
              .sortBy('ordering')
              .groupBy('title')
              .map((titleSettings, title) => ({
                settingName: title,
                settingDescription: titleSettings[0].description,
                settingInputs: _.map(titleSettings, ({name, value, inputSetting}) => ({
                  inputName: name,
                  inputValue: value,
                  inputConfig: inputSetting,
                })),
              }))
              .value(),
          }))
          .value(),
      }))
      .value();

Answer №1

To organize your data, you can create a mapping of categoryName and groupOrder to establish the desired order, which allows for efficient sorting based on this mapping.

I have optimized and type-safe code that aligns with TypeScript standards:

// Enum definition for compile-time checking
enum CategoryName {
  Personalisation = "Personalisation",
  Notifications = "Notifications",
  Orders = "Orders",
}

// Sort order for both categoryName and group
const categoryOrder: Record<CategoryName, number> = {
  [CategoryName.Personalisation]: 0,
  [CategoryName.Notifications]: 1,
  [CategoryName.Orders]: 2,
};

// Group order configuration
const groupOrder: Record<string, number> = {
  "Group A": 0,
  "Group B": 1,
  "Group C": 2,
};

const sortedGroupedData = _.chain(allData)
  .groupBy('sectionName')
  .map((allData, sectionName) => ({
    categoryName: sectionName as CategoryName,
    categoryItems: _.chain(allData)
      .groupBy('group')
      .map((groupSettings, group) => ({
        group: group,
        groupSettings: _.chain(groupSettings)
          .sortBy('ordering')
          .map(({ name }) => ({
            settingName: name,
          }))
          .value(),
      }))
      .sortBy(groupItem => groupOrder[groupItem.group])
      .value(),
  }))
  .sortBy(item => categoryOrder[item.categoryName])
  .value();

console.log(sortedGroupedData);

(Alternatively), if you prefer sorting groups alphabetically

enum CategoryName {
  Personalisation = "Personalisation",
  Notifications = "Notifications",
  Orders = "Orders",
}

// Define sort order for categoryName
const categoryOrder: Record<CategoryName, number> = {
  [CategoryName.Personalisation]: 0,
  [CategoryName.Notifications]: 1,
  [CategoryName.Orders]: 2,
};

const sortedGroupedData = _.chain(allData)
  .groupBy('sectionName')
  .map((allData, sectionName) => ({
    categoryName: sectionName as CategoryName,
    categoryItems: _.chain(allData)
      .groupBy('group')
      .map((groupSettings, group) => ({
        group: group,
        groupSettings: _.chain(groupSettings)
          .sortBy('ordering')
          .map(({ name }) => ({
            settingName: name,
          }))
          .value(),
      }))
      .sortBy(groupItem => groupItem.group.toLowerCase()) // Groups sorted alphabetically
      .value(),
  }))
  .sortBy(item => categoryOrder[item.categoryName])
  .value();

console.log(sortedGroupedData);

You can choose the method that best fits your needs.

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

Setting a value for the identifier just one time

I've been grappling with an issue that's been on my mind for some time now. There are 14 divs on my webpage, and I need each one to be given a random ID (ranging from 1 to 14) every time the page loads. These divs all share the class ".image-box ...

Steps for utilizing Bazel to compile TypeScript

Calling all Bazel (Blaze) experts: I'm curious about the best method for integrating Bazel as a build system for cutting-edge web applications built in Typescript. Is there a preferred setup or perhaps a template that demonstrates this integration? T ...

What is the most strategic way to conceal this overlay element?

Currently, the website I'm developing features a series of navigation elements at the top such as "Products" and "Company." Upon hovering over the Products link, an overlay displays a list of products with clickable links. Positioned at the top of the ...

How to Update a Subdocument in MongoDB

I'm in the process of setting up a database for my Giveaway Bot. It consists of 2 collections: Main (which holds settings) and Giveaway, nested under the Main collection. I've had no issues creating my giveaways, but now I want to add additional ...

What is the correct way to understand nested and intricate types in Typescript?

There seems to be an issue with Typescript not properly inferring complex and nested types at times. I'm trying to figure out if this is a bug or if there's a mistake on my end. And if it's a mistake on my end, what is the most effective wa ...

Is it possible to integrate Vue.js within a web component?

Is it possible to utilize VueJS to control behavior within a web component? In other words, if the VueJS library is included as a script reference, can it be integrated in the same way as on a standard HTML page, but within the confines of a web componen ...

Uploading Files Using the Dropbox API Version 2

Before, I integrated the Dropbox API V1 into my web application to upload files to my personal Dropbox account. The app was configured to use only one specific dropbox account for file uploads. Previous Process: I registered an app on the dropbox develo ...

Issue with Bootstrap/Bootswatch Dropdown Tab Not Showing Up

I am encountering an issue while trying to implement a tab with a dropdown navigation, similar to the examples shown on Bootswatch. Interestingly, it seems that this functionality is not working properly even on the demo page provided by Bootswatch. My ma ...

Comparing various indexes within an array using JavaScript array functions

I am currently facing a challenge with comparing non-consecutive indexes in an array. For instance, how can I compare index 0 with all the other indexes until reaching index 3 in a given array like this: const arr = ["Juan", "Maria", & ...

Exploring the functionality of Radar Chart within a React component

Within the index.html file that is being utilized, there exists a javascript code specifically designed for the chart function. <script src="js/plugins/chartJs/Chart.min.js"></script> var radarData = { labels: ["In Perso ...

What is the best way to prompt users to submit comments with a popup textarea box?

Within my project, I have incorporated a dropdown list: <div class="dropdown"> <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Select subject <span class="caret"></span> </but ...

Utilizing React Router with Material-Table for Efficient Column Value Filtering

Is there a way to dynamically pass Route params into the filtering fields of a React table component? I am currently utilizing the material-table component and have a list of links structured like this: <ul> <li> <Link to="/Products/ ...

Using an `<img>` element as an event handler in a JavaScript function

I'm having trouble setting up a click handler for the search field in my project. I've tried using on() with an img or class, but it's not working as expected. When adding the image using the code below: jQ('#psc').append('&l ...

How can I use JavaScript to loop through a specific attribute?

I have implemented ckeditor inline on a website I created. While it allows me to save data to a database, the issue arises when ckeditor automatically applies its own classes and attributes to certain elements where contenteditable is enabled. It also re ...

Prevent unauthorized manipulation of specific objects' hrefs in Javascript / Identify the source of href modifications

I am currently dealing with an outdated application that populates a div by initiating a JavaScript function on a remote server and then injecting the resulting content into the DOM. Interestingly, when using Firefox, the application unexpectedly alters a ...

What is the best way to transmit the server response information from a fetch API to the client?

After receiving a response with the expected results from an API call using fetch API and a json object, I am looking for ways to send these results to the client in order to display them on the interface. The server-side operation was conducted through th ...

Obtain the view property access while invoking render function as a callback

When working with the guid variable in the render() function, I encountered a limitation where I could only pass it to the constructor. Here is an example of the code I used: app.views.CompanyView = Backbone.View.extend({ el: '#company-view' ...

What is the best way to integrate a CommonJS module into an ES6 module within a Node.js

I am working on a node app and I want to adopt the ES6 module format without transpiling down to ES5. However, I still want to integrate older libraries like express and socket.io that use CommonJS / require format. What solutions are available for combi ...

Loading information into a Mongoose array schema

Currently, I am encountering a conceptual challenge along with a real error. My current project involves developing an inventory module concept that comprises of two models: Inventory Item The Inventory model solely consists of an "items" field, which s ...

Achieve iframe resizing using only pure JavaScript, no reliance on jQuery required

I have a question about an iframe on my webpage. <iframe class="myframe" src="some_page.html" width="800px" height="600px" /> Is there a way to make this iframe resizable like the <textarea></textarea> tag? I prefer to achieve this wit ...