Mohamed Sahir
Mohamed Sahir

Reputation: 2543

Mapping an RXJS observable efficiently

I have two different arrays of objects, how to reassign the array of object properties.

Using key to label:

export interface ProductData
{
    key:string,
    name:string
}


productData:[          
    {key:'index1',name:'invoice'},   
    {key:'index2',name:'Multi'}
];

Using name to value:

export interface filterOptions{
  label:string;
  value:string;
}

Here is how I handle the resulting call from my service:

this.myService.getProctResponse.subscribe(response=>{    
    this.filterOptions[0].label = response.productData[0].key;
    this.dfilterOptions[0].value = response.productData[0].name;
    this.filterOptions[1].label = response.productData[1].key;
    this.filterOptions[1].value = response.dproductData[1].name;
});

This works (solution 1), but I must provide the index of each value in order to map it.

I'd rather do something like this:

this.productData.map(items=>{     
    this.filterOptions.value= items.name
    this.filterOptions.label = items.key
});

Problem: It will push the last value as an object, and not provide not array of object.

This approach works better than solution 1 (above), but is there a better approach I could be using instead?

 response.productData.forEach((item, index) => {
    let list :FilterModel = {
      label:item.key,
      value:item.name
    };

    this.filterOptions.push(list);
  });

My issue here is still needing to map the key property to the label property and and name property to the value property.

expected o/p:

[{label:'index1',value:'invoice'},
{label:'index2',value:'multi'},
{label:'index3',value:'single'},
{label:'index4',value:'handy'},etc];

Upvotes: 0

Views: 448

Answers (1)

Whit Waldo
Whit Waldo

Reputation: 5207

As you identify, having to bind specifically to index values in the response is unwieldly and unfeasible for a number of reasons. What if the response array contains more than two objects? What if it contains fewer?

But as you also note, you do have a need to map between each of the properties of your different interfaces. Because you're using RXJS to process the values from your remote call, I would suggest just simplifying this a bit to run the mapping within your observable process as in the following:

this.myService.getProctResponse.pipe(
  map(x => {
    let models: Array<FilterModel> = [];
    x.forEach(y => {
      let model: FilterModel = {
        label: y.key,
        value: y.name
      };

      models.push(model);
    });
    return models;
  })
).subscribe(mappedResponse => {
  //Do something with it
});

It merely combines a few of the ideas you already have, but puts it in the pipe method so that it's calculated only when the observable pushes any data through it. As before, you just subscribe to this and instead of receiving ProductData[] and subsequently processing it, you'll receive FilterModel[] to assign where you need to, simplifying any dependent associations to your component markup.

Upvotes: 1

Related Questions