When using Angular 2 RC1 and TypeScript, the getById method in HTTP creates a new instance that does not include a required Array

I received valuable assistance for a previous issue at: "TypeError.parent.context.car.getBrands is not a function": s, which is closely related to my current question. The root of the problem lies in the fact that my application fails to function unless I create a new instance of "car" and then call the method:

getById(id: string) {
   return this.http.get('app/car.json'+id)
     /*
       if I log the incoming data here to the console, 
       the correct data from server comes, e.g. 'id: id, name: name, brands: Array[2]'
     */
     .map(data => data.json())
     .map(car => new Car(car.id, car.name));  //<== this line causes problem!
}

The component receiving the data looks like this:

routerOnActivate(curr: RouteSegment): void {
    let id = curr.getParam('id');
    this._service.getById(id)
        .subscribe(car => {
            // This code executes upon receiving the server response
            this.car = car;
            console.log("res: ", this.car); // <=== correct car without the array of brands
        });
    // Code here is executed before the server response despite being written below   
}

When a new instance of "Car" is created, it contains an empty Array of Brands.

This is how my service is structured:

@Injectable()
export class Service {

    constructor(private http: Http) { }

    getCars(){
        return this.http.get...       
    }

    getById(id: string) {
        return this.http.get...       
    }    
}

And here is how my Car class is defined:

export class Car {

    private brands: Array<Brand>;

    constructor(public id: string, public name: string) {
        this.brands = new Array<Brand>();
    }

    public getBrands(): Array<Brand> {
        return this.brands;
    }
    // Some other methods.
}

Even though there is data in the brands Array, the getById method only retrieves the id and name parameter, leaving the brands array empty. I am uncertain about how to retrieve the data from the server while including the array of brands!

I have tried creating a Car object within my service, which logs the correct data but does not effectively work.

getById(id: string) {
        this.http.get('app/car.json'+id)
        .map((res: Response) => res.json())
        .subscribe(car => {
            // This code is executed when the server response arrives
            this.car = car;
            console.log("res: ", this.car); // <==== correct data!
            return this.car;
        });
            // Placing return this.car here doesn't give a void error, but results in an undefined car due to premature execution before subscribe!
}

When attempting to receive the data in the component:

routerOnActivate(curr: RouteSegment){
    let id = curr.getParam('id');
    this.car = this._service.getById(id); // Error: Type 'void' is not assignable to type 'Car'
}

Any guidance would be greatly appreciated! Thank you!

Answer №1

After a long period of time, I finally found the solution to my issue and wanted to share it here. I needed to create a static method in order for the application to function correctly. Here is the code snippet:

getById(id:string)
    return this.http.get('app/car.json'+id)
      .map(data => data.json())
      .map(data => Car.carFromJSON(data))

In the Car class implementation:

static carFromJSON(json) {
    let id = json.id
    let name = json.name
    let brands: Brand[] =
        json.brands.map (brand => new Brand())
    return new Car(id, name, brands)
}

Answer №2

Each time you create a new Car instance, you are initializing it with an empty array:

export class Car {

    private brands: Array<Brand>;

    constructor(public id: string, public name: string) {
        this.brands = new Array<Brand>(); // Each new Car() ends up with an empty array
    }

    public getBrands(): Array<Brand> {
        return this.brands;
    }
    //other methods here.
}

To fix this issue, you need to modify your constructor to include brands:

constructor(public id: string, public name: string, public brands: Brand[]) {}

Then make sure to update your method as follows:

getById(id: string) {
   return this.http.get('app/car.json'+id)
     .map(data => data.json())
     .map(car => new Car(car.id, car.name, car.brands));  // Remember to include brands
}

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

The issue of losing context when using Papaparse with an Angular 4 function

Check out this block of code httpcsv2Array(event) { var gethttpcsv = Papa.parse('https://docs.google.com/spreadsheets/d/e/yadyada/pub?output=csv', { download: true, header: true, ...

What is the process of personalizing a DaisyUI theme in Tailwind with TypeScript?

I am trying to tailor an existing DaisyUI theme using my tailwind.config.ts file for my Next.js project. Although the DaisyUI documentation only provides examples in JavaScript (text), I want to customize it within my TypeScript environment. Below is a s ...

What is the reason behind the NgForOf directive in Angular not supporting union types?

Within my component, I have defined a property array as follows: array: number[] | string[] = ['1', '2']; In the template, I am using ngFor to iterate over the elements of this array: <div *ngFor="let element of array"> ...

The filter() and some() functions are not producing the anticipated output

Currently, I am in the process of developing a filtering mechanism to sift through a dataset obtained from an API. The array that requires filtering contains objects with various parameters, but my aim is to filter based only on specific parameters. For ...

What is the process for integrating a pre-existing CDK module into a fresh code pipeline stage?

I am in the process of setting up a new AWS code pipeline to integrate an old CDK module with a newer module. Following the instructions provided in this workshop, I have successfully created a code pipeline that fetches the source code from CodeCommit, bu ...

How to show table cell value in Angular 4 using condition-based logic

I am a beginner in Angular development. Here is the HTML code I am working with: <tr *ngFor="let item of calendarTableSelected; let idx = index"> <span *ngIf="idx === 0"> <td style="width:15%;" *ngFor="let name of item.results" ...

How do I create a standalone .ts file with Angular 9?

Just diving into Angular development and eager to create a standalone .ts file without having to generate an entire component. Can anyone guide me on how to achieve this using ng generate? Scenario: During the application build process, I need to write th ...

Working with TypeORM to establish two foreign keys pointing to a single primary key in a table

For my project, I am looking to establish bi-directional ManyToOne - OneToMany relationships with two foreign keys that reference the same primary key. Specifically, I have a 'match' table that includes two players from the 'player' tab ...

Retrieve a collection within AngularFire that includes a subquery

I have the following function getParticipations( meetingId: string ): Observable<Participation[]> { return this.meetingCollection .doc(meetingId) .collection<ParticipationDto>('participations') .snapshotCh ...

Leveraging the browser's built-in validation error messages in Angular for HTML forms

Is there a way to incorporate browser's native HTML validation error messages into Angular applications? https://i.sstatic.net/J0em4.png What I am looking for is the ability to leverage the built-in error messages when working with reactive forms li ...

I'm encountering a 404 error on Next.js localhost:3000

Embarking on a fresh project in Next.js, my folder structure looks like this: https://i.stack.imgur.com/HhiJo.png However, upon navigating to localhost:3000, I am greeted with a 404 error screen. It seems there is an issue with the routing, but unfortuna ...

Managing asset paths post ng build: A guide

I've been attempting to use assets to display svg icons on my ESRI map. I'm working with Angular9 and the esri js api, trying to add a symbol from a URL. Locally, the svg appears on the map, but once I build and deploy the project to IIS, it sta ...

Is there a way to incorporate an external JavaScript file into a .ts file without the need for conversion?

I have an external JavaScript file that I need to utilize in a .ts file without performing any conversion. Does anyone know how to use it within TypeScript without the need for conversion? ...

Replacing the '+' character with a space in HttpParams within Angular 6

When passing a JSON object using HttpParams, the + character is automatically converted to a space before being sent to the backend. Despite trying multiple solutions, I have been unable to resolve this issue for a JSONObject string. this.updateUser({"nam ...

Mastering Two-Way Binding in Angular 2 with JavaScript Date Objects

I am currently utilizing Angular 2 and have encountered the following code: Within the JS file, this code initializes the employee-variable for the template: handleEmployee(employee : Employee){ this.employee = employee; this.employee.sta ...

TypeScript integration for express-validator

Recently, I made an attempt to switch my NodeJS project with ExpressJS to TypeScript for better organization and type safety. However, I encountered an issue with the 'express-validator' middleware during this conversion process. To resolve thi ...

Error code TS 2322 reported in several HttpClient services following the transition from Angular 5.2 to version 6.0.7

Currently, I am in the midst of updating my project to Angular 6 with TypeScript version 2.7.0. Previously, in Angular 5.2.12, my service methods were written like this: isPartDraft = (part: number): Observable<boolean> => this._http.get(`${thi ...

I'm having trouble linking MikroORM migration to Postgresql - the npx command keeps failing. Can anyone offer some guidance on what

I am encountering a situation similar to the one described in this post. I'm following Ben Awad's YouTube tutorial: you can see where I am in the tutorial here. Objective: My goal is to execute npx mikro-orm migration:create in order to generate ...

Using Typescript to pass an interface as an argument to a function that requires a JSON type

Here is an extension related to the topic of Typescript: interface that extends a JSON type Consider the following JSON type: type JSONValue = | string | number | boolean | null | JSONValue[] | {[key: string]: JSONValue} The goal is to inform type ...

Retrieve an established SQS eventSource in AWS CDK

When working with AWS CDK, there is a built-in function called addEventSource that allows you to easily add new SQS triggers (eventSources) to a lambda function. However, I'm curious if there is a way to access and modify the existing eventSources ass ...