An effective way to retrieve a property from an observable by utilizing a pipe

I'm having trouble storing an OrderState object in my ngrx store and extracting data from it for my UI using the async pipe. Specifically, I want to retrieve a child property from this observable object.

order.state.ts

export interface OrderState {
    stage: number;
    postcode: string;
}

app.component.ts

...
export class AppComponent {
  counter: Observable<number>;
  readonly orderState$: Observable<OrderState>;

    constructor(
      private appStateStore: Store<AppState>,
      private counterActions: CounterActions,

      private orderStateStore: Store<OrderState>,
      private orderActions: OrderActions,
    ) {

    this.counter = appStateStore.select('counter');
    this.orderState$ = orderStateStore.select(store => store);
    }
...

app.component.html

<div>Stage: {{ (orderState$ | async)?.stage }}</div>

What is the syntax needed to access the stage property from my orderstate object?

When I display {{ orderState$ }}, I only see [Object object]. Am I not selecting from my store correctly?


Update: There seems to be a basic issue here. I tried this to understand what's happening...

app.component.ts

stage: number

...

    this.orderStateStore.select(s => s).subscribe((data:OrderState) => {
      this.stage = data.stage;
      console.log(this.stage);
    });

app.component.html

<div>Stage: {{ stage }}</div>

In the console, I can see that stage reports as undefined. This might be contributing to the problem. It seems like I cannot set the stage of my component inside this arrow function.


Update: The behavior is quite perplexing...

order.state.ts

export interface OrderState {
    stage: number;
    postcode: string;
}

app.component.ts

...
this.orderStateStore.select(s => s).subscribe((data:OrderState) => {      
  console.log('--- START ---');
  console.log(data);
  console.log('Stage: ' + data.stage);
  console.log('--- END ---');
});
...

Here's what I observe in the console...

https://i.stack.imgur.com/jzxU6.png

It appears that data isn't actually of type OrderState. Instead, it is the wrapper type around OrderState called AppState. Although I attempt to log data.orderState.stage to obtain the value 1, TypeScript throws an error stating that orderState is not a property of data - even though it clearly is based on the console output!

Answer №1

When utilizing {{ orderState$ }}, you may notice it displays [Object object] because it converts the async pipe result (an object) to a string. To extract a specific property using a pipe, consider this approach:

{{orderState$ | async | asyncField : 'stage'}}

The custom pipe code would resemble:

@Pipe({name: 'asyncField'})
 export class AsyncFieldPipe implements PipeTransform {
     transform(object, key: string){
        return object[key];
     }
 }

This setup passes the async pipe result to the created pipe and retrieves a designated field. For reference, a functional plunkr can be found here.


Update: An alternative to using a pipe involves employing the rjxs map method to filter what is returned from the observable sequence. This method offers more flexibility for accessing response properties, potentially requiring a more intricate transformation function in the component.ts file.

this.orderState$ = orderStateStore.select(store => store).map(res => res.stage);   

For a demonstration, refer to this functioning plunkr here.

Answer №2

Follow these steps to extract the current stage from the asynchronous order state: {{(orderState$ | async).stage}}

Answer №3

It appears that my initial selection from the ngrx store was incorrect.

MISTAKE

this.orderState$ = orderStateStore.select(store => store);

CORRECTED

this.orderState$ = appStateStore.select(x => x.orderState);

In hindsight, it is clear that I should have accessed the orderState directly within the appStateStore. The structure of my store objects is as follows:

app.state.ts

export interface AppState {
  counter: number;

  orderState : OrderState;
}

order.state.ts

export interface OrderState {
    stage: number;
    postcode: string;
}

OrderState is a subset of AppState. Therefore, I needed to access the orderState property using the => function when querying the appStateStore.

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

What is the process for refreshing the dropdown menu in angular2 after modifying the data in the typescript file?

Right now, I am implementing angular2 in my project. I have a dropdown component labeled as CFC Filter {{val}} In the typescript file, I have defined this.filters = ["0", "60", "100", "180", "600", "1000"]; If the filter value retrieved from the da ...

Navigating routes for a module sourced from NPM: Best practices

Looking for guidance on loading Angular routes from an NPM module? Take a look at this snippet from my app.module.ts file: import { HelloWorldModule } from 'hello-world-app-npm/hello-world-app.umd.js'; // Loading module from NPM const routes = ...

What steps should I take to ensure that a cookie has been properly set before utilizing it?

I'm in the process of developing a JWT authorization code flow using Next.js and NestJS. Below is the POST request being sent from the frontend to the backend server: const response = await fetch( 'http://localhost:4000/auth/42/callback?code=& ...

Guide to displaying a unique custom modal popup when angular page is reloaded

Upon clicking the refresh button on the browser, a personalized popup should appear for confirmation. By utilizing @HostListener('window:beforeunload', ['$event']), it is possible to monitor the event; however, replacing the JavaScript ...

Exploring the Angular lifecycle hooks for directives: AfterContent and AfterView

According to the Angular documentation, it is stated that AfterContent and AfterView lifecycle hooks are intended for components and not directives. Surprisingly, I have a directive that seems to be using them without any issues. What potential limitation ...

Utilizing indexes to incorporate elements into an object array

I'm currently working on a project using Angular. I have an index coming from the HTML, and here is the code snippet: save(index){ //this method will be called on click of save button } In my component, I have an array structured like this: data = [{ ...

What benefits do declaration files offer compared to sources in TypeScript?

When developing and releasing a library using TypeScript, there are 2 approaches: One option is to generate declaration files d.ts along with the bundled JavaScript file and then specify it in package.json with: "types": "./dist/mylib.d.ts" Alternativel ...

Creating a personalized aggregation function in a MySQL query

Presenting the data in tabular format: id | module_id | rating 1 | 421 | 3 2 | 421 | 5 3. | 5321 | 4 4 | 5321 | 5 5 | 5321 | 4 6 | 641 | 2 7 | ...

Tips for invoking an Android function from an AngularJS directive?

I am facing an issue with my HTML that uses an AngularJS directive. This HTML file is being used in an Android WebView, and I want to be able to call an Android method from this directive (Learn how to call Android method from JS here). Below is the code ...

The value of form.formGroup is not equivalent to the output of console.log(form)

Having an issue here. When I send a Form to a component, If I use console.log(form), it displays the object correctly. However, when I check the form in the console, the form.formGroup.value looks fine (e.g. {MOBILE0: 'xxx', PHONE0: 'xxx&ap ...

Is it possible to create a prototype function within an interface that can group items in an array by a specific property, resulting in an array of objects containing a key and corresponding array of values?

I've been working on this code snippet and I'm trying to figure out how to make it work: Array<T>.groupBy<KeyType> (property): {key: KeyType, array: Array<T> }[]; The code looks like this: type ArrayByParameter<T, KeyType = ...

Removing a field from a collection using firebase-admin: Tips and tricks

I currently have a collection stored in Firebase Realtime Database structured like this: My requirement is to remove the first element (the one ending with Wt6J) from the database using firebase-admin. Below is the code snippet I tried, but it didn' ...

Unresponsive Textbox Input Issue within Reactive Form

My current setup involves an Angular Reactive Form with various controls: this.taskForm = this.formBuilder.group({ storyNumber: new FormControl('', [Validators.required, Validators.pattern('^[A-Z]{2,}[0-9]*-[0-9]{2,}$')]), ...

Guiding TypeScript to autonomously deduce the precise types of an object that implements a generic interface

Within this code snippet, TypeScript appears to be unaware of the specific type associated with userService.getByUserId in the final line. The expected type should be (userId: string) => ServiceResult<User>, but TypeScript is enforcing a more gene ...

Displaying data labels overlaid on top of data points in line charts

Currently, I am utilizing Angular2 along with ng2-charts to generate a line chart. My objective is to position the data labels directly above the points, similar to how they appear in the bar chart showcased in this image: bar chart I stumbled upon the ch ...

What causes the discrepancy in results between these two NodeJS/Typescript imports?

Within my NodeJS project, I have integrated typescript version 3.2 alongside express version 4.16 and @types/express version 4.16. My development is focused on using Typescript with the intention of transpiling it later on. The guidelines for @types/expre ...

Exploring the features of the window object in an Angular application compiled ahead of time

In an effort to streamline our development process and avoid having to build the Angular-App multiple times for different environments, we decided to skip injecting environment-specific variables (such as service endpoints) into our app using regular file ...

Typescript: create a type similar to keyof but with a particular value type

I have an interface called MyInterface interface MyInterface { field1: boolean, field2: MyType, field3: MyType } In this interface, I want to create a new type that contains only the keys which have values of type MyType. While I know about the key ...

What is the proper way to declare app.use using TypeScript with the node.js Express module?

I am working on a node.js app that utilizes typescript with express. In my code, I have defined an error middleware function as shown below: app.use((error:any, req:Request, res:Response, next:NextFunction) => { res.status(500).json({message:error.m ...

Tips for including and excluding personalized Chips from input

Just started learning React/typescript, any assistance would be greatly appreciated Custom Chip (CC.chip) is a specialized Chip UI component that can be utilized as demonstrated below. const [isOpen, setIsOpen] = useState(true); const onClose = Re ...