Is there a straightforward method in Typescript to transform arrays of arrays into objects that adhere to the type specified by `<my model>`?

Currently working with Angular 6, I am seeking a straightforward solution for handling multiple models that define the structure of various arrays of values. Rather than manually iterating through each element within the arrays to populate model instances using For-loops, I am in search of a more streamlined approach. Some of these models may be intricate, involving nested levels.

For instance:

Model:

export class User {
    firstName = '';
    lastName = '';
    userName = '';
    email = '';
}

Array:

[
["Adam","Richardson","AdMan","<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bdfcd9dcd0fdd8c5dcd0cdd1d893ded2d0">[email protected]</a>"],
["Ahmad","Ali","MarketMan","<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="23624b4e424763465b424e534f460d404c4e">[email protected]</a>"],
["Feng","Trunk","SuperMan","<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bcfad9d2dbfcd9c4ddd1ccd0d992dfd3d1">[email protected]</a>"],
["Chris","Garcia","SmartMan","<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e4a08b8a858880a4819c8589948881ca878b89">[email protected]</a>"] 
]

Is there a method to seamlessly map a model onto a value-only array?

Answer №1

If you need a universal method for populating any object with data from an array of values, here is how you can achieve it (provided that the properties in the class are declared in the same order as the data in the array):

class User {
    firstName = '';
    lastName = '';
    userName = '';
    email = '';
}

const data = [
    ["Adam", "Richardson", "AdMan", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f3b297929eb3968b929e839f96dd909c9e">[email protected]</a>"],
    ["Ahmad", "Ali", "MarketMan", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="88c9e0e5e9ecc8edf0e9e5f8e4eda6ebe7e5">[email protected]</a>"],
    ["Feng", "Trunk", "SuperMan", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e2a4878c85a2879a838f928e87cc818d8f">[email protected]</a>"],
    ["Chris", "Garcia", "SmartMan", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="490d262728252d092c31282439252c672a2624">[email protected]</a>"]
];

function fromDataArray<T>(klass: new () => T, data: any[]) {
    const obj = new klass();
    Object.keys(obj).forEach((k, i) => obj[k] = data[i]);

    return obj;
}

const users = data.map(d => fromDataArray(User, d));

When dealing with nested objects, one challenge is losing type information once TypeScript is transpiled to JavaScript. To address this issue, ensure that your classes have initial objects that instantiate properties meant to be objects with instances of their respective types.

The following example demonstrates handling nested object data arrays:

function fromDataArray<T>(klass: new () => T, data: any[]) {
  const obj = new klass();
  Object.keys(obj).forEach((index, value) => {
    if (Array.isArray(obj[index])) {
      if (obj[index].length && typeof obj[index][0] === "object") {
        obj[index] = data[value].map(innerData => fromDataArray(obj[index][0].constructor, innerData));
      }
      else {
        obj[index] = data[value];
      }
    }
    else if (typeof obj[index] === "object") {
      obj[index] = fromDataArray(obj[index].constructor, data[value])
    }
    else {
      obj[index] = data[value];
    }
  });

  return obj;
}

// Classes for nested objects
// Data array structure provided for demonstration

const crazyData = data.map(d => fromDataArray(Class1, d));

The output will be an array of objects formatted accordingly:

Note: This view presents JSON representation, but the data objects retain their specific types.

{
    "firstName": "Adam",
    "subClass1": {
        "lastName": "Richardson",
        "subClass2": {
            "userName": "AdMan",
            "stuffz": [
                {
                    "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0c4d686d614c69746d617c6069226f6361">[email protected]</a>"
                }
            ]
        }
    }
}

Answer №2

Have you thought about utilizing Array.prototype.map to convert each element in the main array?

function createUserFromData([first, last, username, email]) => {
    const user = new User();

    user.first = first;
    user.last = last;
    user.username = username;
    user.email = email;

    return user;
});

// If "data" is the name of the array of arrays
data.map(createUserFromData);

Answer №3

If you're looking for a solution, the code below can help achieve the desired outcome (refer to this stackblitz for a demonstration). This code maps the properties of the User object to the values in the corresponding array, maintaining their sequential order.

export class User {
  firstName = '';
  lastName = '';
  userName = '';
  email = '';
}

export class AppComponent {

  users = new Array<User>();

  values = [
    ["Adam", "Richardson", "AdMan", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="175673767a57726f767a677b723974787a">[email protected]</a>"],
    ["Ahmad", "Ali", "MarketMan", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2160494c4045614459404c514d440f424e4c">[email protected]</a>"],
    ["Feng", "Trunk", "SuperMan", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4204272c2502273a232f322e276c212d2f">[email protected]</a>"],
    ["Chris", "Garcia", "SmartMan", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c682a9a8a7aaa286a3bea7abb6aaa3e8a5a9ab">[email protected]</a>"]
  ];

  createUsers() {
    this.values.forEach((value) => {
      let user = new User();
      Object.keys(user).map((key, index) => {
        user[key] = value[index];
      });
      this.users.push(user);
    });
  }
}

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

Listen for changes in the div height in Angular 2 using HostListener

After spending hours researching Event Listeners in Angular 2, it's clear that there is a lack of comprehensive documentation on the topic. My goal is to set the height of various div groups (generated using ngFor) to match the height of the tallest ...

Retrieve data from Outlook Calendar API by utilizing OAuth2 protocol

I have been working with calendar APIs in .NET Core and Angular. After successfully integrating the Google Calendar API, I am now looking to implement the Outlook Calendar API as well. To start off, I need to create a function in Angular that will allow me ...

When downloading text using Angular, the file may not display new line characters correctly when opened in Notepad

When downloading text data as a .txt file in my Angular application using JavaScript code, I encountered an issue. Below is the code snippet: function download_text_as_file(data: string) { var element = document.createElement('a') eleme ...

Angular 2: Issue with FormControl returning empty value

I'm currently working with a form <form [formGroup]="form"> <input type="text" value={{userDetails.first_name}} formControlName = "firstName"> <button type="submit" data-action="save" (click)="onSubmit(form.value)"> </fo ...

What is the best way to utilize external module imports for SVG React components in a create-react-app project?

Understanding the Project Structure To ensure code reusability across multiple React projects, a specific project structure has been established: @foo/design: Includes design elements like raw SVG images @foo/ui: A React library based on Create React App ...

The superclass defines the type of the subclass

There is an abstract typescript class like this: abstract class Abstract { constructor (public parent?: Abstract) { } } Then, two subclasses are defined as follows: class Sub1 extends Abstract { } class Sub2 extends Abstract { } The issue aris ...

Issue with next.handle not functioning properly in Angular 8 when re-requesting

In the code snippet below, the issue is that even after the token expires (401), the API for fetching the refresh token is called, but the request is not re-sent with the updated token using the inner next.handle(). export class InterceptService implements ...

Angular dynamic component for resizing the screen with horizontal split dimension adjustment

I am currently developing a dynamic component that has the ability to house multiple full-height panel components, allowing for their widths to be resized and adjusted as needed. For instance: https://i.sstatic.net/TMtHt38J.png Initially, the container& ...

The output of the Angular2 resolver is undefined, even though the data service successfully logs the data without any

Trying to preload data before showing the component using angular2's resolver is my current challenge. In my data.service.ts file: I created a function that fetches employee details: getEmployee(id:string) { let headers = new Headers(); ...

Issue with absolute positioning in Primeng components when a p-selectButton is added

I'm just starting to explore primeng, and I encountered this html snippet: <div class="main wheel"> <div class="wheel-part use"> <img src="./assets/images/svg/path-use.svg"> <span cl ...

The nebular toggle feature fails to function properly when the application is in production mode

On my webpage, I have a nb-toggle HTML element. While it functions properly in debug mode, the production version displays like this: https://i.sstatic.net/5qiPB.png Any ideas on what might be causing this issue? https://i.sstatic.net/Trqtt.png When r ...

Angular Leaflet Bootstrap Div positioned on top of the map

I am attempting to place a div above the map in order to include some actions such as filters, but the div only becomes visible when I move the map and then it goes behind the map. Component CSS: .map { padding: 0; position:relative; width:10 ...

Troubleshooting Angular2 Error: Incompatibility with TypeScript - Unable to Assign String

While working on creating a custom pipe in Angular2 for filtering, I encountered the following build error: Error TS2322: Build: Type '() => string' is not assignable to type 'string' Below is my sample code: import { PipeTransf ...

How to Stop NgFor Loop in Angular 2

In my current project, I am attempting to iterate through an array using the *ngFor directive in my template. I am also trying to search for a specific element based on its key, utilizing the *ngIf directive. However, once the condition is met with the k ...

Change rem into a whole number

How can I convert a rem value to an integer? The code snippet this.props.viewTitleContainerStyle.paddingTop returns a value of 1.00rem in the debugger. The viewTitleContainerStyle is stored as theme.sizes.Measures.Measure100. I need to convert this to an ...

Angular update row and save data to an array

When comparing the data of an edited row with the row just below it, I encounter a specific scenario. In a table containing 5 rows, as I edit records from top to bottom using the provided code snippet, I am able to store the values in an array. The most re ...

Attempting to categorize JSON object elements into separate arrays dynamically depending on their values

Here's the JSON data I'm currently working with: ?$where=camis%20=%2230112340%22 I plan to dynamically generate queries using different datasets, so the information will vary. My main objective is to categorize elements within this array into ...

Is there a way to change the names of bundles created during ng serve in Angular 13?

I am looking to change the names of bundles created after running ng serve in an Angular Application. Currently, the bundles are: vendor.js polyfills.js styles.css styles.js main.js runtime.js I want to rename these ...

Deleting an element in an Array of objects using Typescript

export class AppComponent implements OnInit { title = 'bucketList'; bucketList: BucketListItem[] = [ new BucketListItem( "Goa Trip", "Travel to Goa" ) ]; ngOnInit() { } onItemAdded(eventData) ...

The connection between Cognito identity and Mqtt is not possible within AWS IoT Core

The application is built using Angular. Upon logging in with Cognito, the application retrieves the user's CognitoUser data, including id token, access key, and session token. Next, the application connects to Iot Core to subscribe to or publish data ...