Transform the data prior to sending it back as an observable

I am fairly new to Angular 2 and the idea of Observables. However, what I am trying to accomplish should be quite simple for experienced experts :)

Here's the situation: I have a component where I have subscribed to an observable coming from a service. In order to test my components, I have been using data arrays. Now that I'm done testing, I want to connect real API calls to my service. The issue arises when I try to manipulate the data received from the server before returning it to the component. This manipulation causes an error saying "cannot read property 'subscribe' of null."

This error occurs because in my service's observable, I send an API request using the HTTP.get method and the code doesn't wait for the response to finish. Although I do receive the result from the server, it comes after the error in the console.

Could someone please provide guidance on how to make an HTTP call, manipulate its data, and then send it to the subscribed component?

Below is the code snippet from my component:

getSearchResults(keyword, parentId?, subCatId?) {
    this.subscriptionResults = this.catalogService.getSearchResults(keyword, parentId, subCatId)
        .subscribe(
            data => {
                // Manipulate the received data here
                if ( this.debugMode ) {
                    console.log('RESULTS: ', data);
                }
            },
            error => this.errorMessage = <any>error
        );
}

And here is my service code:

// Get data from server
getDataFromServer(URL: string): Observable<any> {
    return this.http.get(URL).flatMap(this.extractData).catch(this.handleError);
}

getSearchResults(keyword: string, parentCatId?:number, subCatId?:number): Observable<any> {

    let URL = this.API_URL + '/search?categoryId=' + subCatId + '&format=json';
    
    // Make API Call
    let request = this.getDataFromServer(URL);

    request.subscribe(
        () => { 
            // Modify the result data here before sending it back 
        },
        error => { console.log('ERROR: ', <any>error); }
    );

I need to manipulate the response data before returning it. How can I achieve this?

-- EDIT -- If I return a BehaviorSubject:

return new BehaviorSubject<any>(request.subscribe(
            res => { return this.processResultData(res, layoutType, keyword, parentCatId, subCatId); },
            err => { console.log('RETURN ERROR: ', <any>err); }
        ));

Instead of receiving the subscription object in my component, I actually need the data inside the subscription.

Answer №1

To ensure your component is subscribing to the return value from getSearchResults(), the function must return an Observable. Since your getDataFromServer() function already returns an observable, you can utilize Observable.map() on that return value to modify the data passing through the observable stream. The new observable generated by Observable.map() will be what your component should subscribe to.

In terms of code implementation:

.map() operation.

Answer №2

Another way to approach this is by using pipable operators in RxJS version 5.5 or newer:

import { map, catchError } from 'rxjs/operators';

After importing the necessary operators, you can then implement it like:

  return this.getDataFromServer(URL).pipe(
      map((response) => {
        // Make any modifications to the response here
      }),
      catchError(error => console.log('An error occurred: ', error))
  );

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

Tips for sorting the mat table dataSource by inputting two columns and selecting the search button

I am currently displaying mat table data with columns for Role, Status, Email ID, and Name. Above the table, there is a search area where users can enter values for Role and Status and then click the Search button. If the entered values match exactly for ...

Utilizing React Router with the power of useCallback

My route configuration is set up as follows: const defineRoutes = (): React.ReactElement => ( <Switch> <Redirect exact from="/" to="/estimates" /> <Route exact path="/estimates" component={CostingPa ...

Creating a Button within the Dialog Component Header in PRIMENG for Angular 4

I need help adding buttons to the dialog window header in primeng. You can find the code at https://www.primefaces.org/primeng/#/dialog. The task is to insert two buttons (with icons like a calculator and question mark) on the right side of the top header ...

Issue with Nuxt2 CompositionAPI: Unable to showcase imported render function in component - Error message states "template or render function not defined"

I have created a render function that I believe is valid. I am importing it into a component and registering it within the defineComponent. However, when running the code, I encounter an error saying "template or render function not defined". I am confide ...

Conflicts arise when trying to create several objects with different material types in ThreeJS within the

Adding a star to the scene caused all objects in the scene to turn white and the perspective of the objects to glitch. Switching the materialStar to new THREE.MeshBasicMaterial fixed the rendering issue. It appears that the problem stems from having multip ...

React Material UI Select component is failing to recognize scrolling event

Having some difficulty understanding how to detect a scroll event with a Select component using Material-UI. The Select has MenuProps={...}, and I want to listen for the scroll event inside it. I've tried putting onScroll within MenuProps={...}, but ...

Angular Ionic: Unable to compare 'value'. Only arrays and iterable objects are permitted for differentiation

I attempted to display a list value and when I logged the value of the list, it appeared exactly how I wanted: unit value {id: 81, name: "3 BR Suite"} unit value {id: 82, name: "3 BR Grande"} unit value {id: 83, name: "Pool Villa&q ...

Launching Angular 2 application on Heroku

Previously, I would combine my Angular 1 and Rails applications and deploy them on Heroku, which always went smoothly. However, now that I've transitioned to Angular 2, I'm looking to segregate my Angular and Rails code. I've successfully cr ...

Tips for effectively changing Observable data into an Array

I am currently attempting to transform an Observable into an Array in order to loop through the Array in HTML using ngFor. The Typescript code I have now is causing some issues. When I check the testArray Array in the console, it shows up as undefined. it ...

Listening to events on the iterative variable of NgFor directive in Angular 2

Angular2 has been my latest exploration in solving a unique data binding challenge. In my UI, I've presented a javascript array of objects like a database recordset in an HTML table. Each row contains menus and inputs allowing users to modify the rec ...

Hidden field in Angular 2 form has an invalid property

I am working with a form object called "formObject" and I am trying to store the validity status of the form in a variable called form.isFormValid. Any suggestions or assistance would be greatly appreciated. export class FormObject { public isFormValid: ...

Unexpected runtime error when using Prisma with NodeJS and Express

While starting the server, I encounter an error message saying [ERROR] 14:48:46 Error: Cannot find module './runtime/library'. The stack trace points to the directory named prisma. Even after executing npx prisma generate, the directory called p ...

Viewing the photo container before uploading while having text overlap

I'm encountering an issue where the image previews are overlapping with the text in another div. Here are the screenshots: the first one shows how it looks before the preview, and the second one shows what happens when images are added: https://i.sst ...

Show a notification if the search bar returns no results

I am facing an issue with my search functionality. When a user searches for something not in the list, an error message should be displayed. However, in my case, if I search for "panadol" in my list, it displays the list containing that word and shows an e ...

Having trouble sending correct true/false values for selected radio buttons on an Angular5 table, often requiring users to click them twice to submit the appropriate values

My goal is to assign true or false values to selected radio buttons in each row and then form an object for submission. To distinguish between the radio button values in each row, I have used {{k}}+{{sizeobj.rbSelected}} as the value which is causing issue ...

Is it possible to release a typescript package without including the ts files in the

I have a Typescript project that needs to be published. All generated JS files are stored in a directory named build, and declaration files in another directory called declaration. I do not want the .ts files to be included in the published version. Can an ...

Issues with Angular displaying filter incorrectly

Whenever a user chooses a tag, I want to show only the posts that have that specific tag. For instance, if a user selects the '#C#' tag, only posts with this tag should be displayed. This is how my system is set up: I have an array of blogs that ...

Vue.js 3 with TypeScript is throwing an error: "Module 'xxxxxx' cannot be located, or its corresponding type declarations are missing."

I developed a pagination plugin using Vue JS 2, but encountered an error when trying to integrate it into a project that uses Vue 3 with TypeScript. The error message displayed is 'Cannot find module 'l-pagination' or its corresponding type ...

How to conceal an element in Angular using its unique identifier

I am looking for a way to toggle the visibility of an element based on its ID. I have a dynamic list with the following structure in my TS component: vehicles = [ { "id": 1, "type": "car", ...

Tips on applying borders to dynamically generated content in jspdf autotable, similar to a template

Having trouble adding borders to my PDF generated using jsPDF autotable. I want the layout to match the template, can someone assist me in resolving this issue? I need the header border to consist of two lines, similar to the template image provided below ...