One method for identifying which observable has been altered in Observable.merge is by examining the output of

Here is a simplified and clear version of my code:

connect(): Observable<Customer[]> {
   const displayDataChanges = [
     this._customerDatabase.dataChange,
     this._filterChange,
     this._sort.mdSortChange,
     this._paginator.page
   ];
   return Observable.merge(...displayDataChanges).map(() => {
     let data = this._customerDatabase.data.slice();
     data = this.getFilteredData(data);
     data = this.getSortedData(data);
     const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
     return data.splice(startIndex, this._paginator.pageSize);
   });
}

This connect() function will provide an Observable array of Customers.

The following section sets up an array of Observables:

const displayDataChanges = [
      this._customerDatabase.dataChange,
      this._filterChange,
      this._sort.mdSortChange,
      this._paginator.page
];

Whenever any of these Observables emit data, it triggers a change in the Array of Customers. This includes when loading data, changing filters, selecting a sorting method, or moving to another page.

All these changes are merged together in order to compose and assemble the final data that needs to be returned. However, this approach is not very efficient as it does not differentiate between which specific observable has emitted new data...

How can I enhance this process and identify the specific observable that triggered the change? (See Pseudo code below)

return Observable.merge(...displayDataChanges).map(() => {

 **[ALWAYS]**
 let data = this._customerDatabase.data.slice();

 **[IF SORTING HAS CHANGED]**
 data = this.getSortedData(data); /* After updating the dataSet */
 **[IF FILTER HAS CHANGED]**
 data = this.getFilteredData(data);

 **[ALWAYS]**
 const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
 return data.splice(startIndex, this._paginator.pageSize);
});

Answer №1

To achieve this, consider having your Observables emit an object containing a specific type identifier. Here's an example:

connect(): Observable<Customer[]> {

   const typify = (type) => {
       return (val) => {
           return { type: type, value: val };
       }
   };

   const dataChanges = [
       this._customerDatabase.dataChange,
       this._filterChange.pipe(map(typify('filterChange'))),
       this._sort.mdSortChange.pipe(map(typify('sortChange'))),
       this._paginator.page
   ];

   return merge(...dataChanges).pipe(map(obj => {

       let data = this._customerDatabase.data.slice();

       if (obj.type === 'filterChange')
       {
           data = this.getFilteredData(data);
       }

       if (obj.type === 'sortChange')
       {
           data = this.getSortedData(data);
       }

       const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
       return data.splice(startIndex, this._paginator.pageSize);
   }));
}

Feel free to experiment with a code snippet that utilizes click and interval observables in this example.

Answer №2

You have the option to utilize combineLatest in place of merge. This way, you have access to an emitted value for each observable that has been merged. To achieve this, simply maintain a reference to the most recent values of mdSortChange and _filterChange, and then compare them to see if they have changed.

Explore CombineLatest documentation here

connect(): Observable<Customer[]> {
  const displayDataChanges = [
    this._customerDatabase.dataChange,
    this._filterChange,
    this._sort.mdSortChange,
    this._paginator.page
  ];

  let lastFilter = null;
  let lastSort= null;

  return Observable
    .combineLatest(...displayDataChanges)
    .map(([newData, newFilter, newSort, newPage]) => {
      let data = this._customerDatabase.data.slice();

      if (newFilter !== lastFilter) {
        data = this.getFilteredData(data);
        lastFilter = newFilter ;
      }

      if (newSort !== lastSort) {
        data = this.getSortedData(data);
        lastSort = newSort;
      }

      const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
      return data.splice(startIndex, this._paginator.pageSize);
 });
}

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 best way to declare a global TypeScript variable in a definition file to make it accessible for import?

My issue revolves around an external JS library that contains a global parameter: function Thing() { ... } ... var thing = new Thing(); I have a TypeScript definition file named thing.d.ts with the following content: declare var thing: ThingStatic; ex ...

Interfacing Node JS with Java Web Services via SOAP

I've been attempting to connect Java web services from a Node.js module, but I'm encountering an error in the wsdl library. Below is my wsdl file: <!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130 ...

Validation is only effective for the initial row and fails to apply to subsequent rows. This may be due to the necessity of including the return true/false statement in my validation process

HTML PHP <div align="center"><input type="text" class="form-control" id="<?php echo $i;?>" name="r2<?php echo $i+1;?>" onblur="mvalidate2()" style="text-align: center; bo ...

Selective Circle Appending Techniques

I am having some issues with my bubble chart code. The data file I am working with contains instances where the GDPperCapita and/or LifeExpectancy values are either 0 or NaN, causing problems when appending circles to the chart. I would like to know if th ...

Odd behavior observed while running npm scripts in the npm terminal

Included in my package.json file are the following dependencies: "devDependencies": { "chromedriver": "^2.37.0", "geckodriver": "^1.11.0", "nightwatch": "^0.9.20", "selenium-server": "^3.11.0" }, "scripts": { "e2e": "nightwatch -c test ...

The GraphQL Resolver function that returns an object

When querying with GraphQL, I receive results in the following format: { "data": { "events": [ { "_id": "65f0653eb454c315ad62b416", "name": "Event name", " ...

Discovering and choosing the appropriate course

I am facing a situation where I need to specifically select an element with the class .foo, but there are two anchor tags, both having the class .foo. However, I only want to select the one without the additional .bar class. How can I achieve this? <a ...

Displaying fresh data from a JSON URL by clicking on a button and dynamically refreshing the view in

Apologies if this question has been asked before, but I couldn't locate it. I’m currently engaged in an Angular project where I’ve loaded an external JSON file using http. The data is presented through ngRepeat. When a button is clicked, I aim t ...

Struggling to filter an Array within an Array based on dates falling between a specific date range

Currently, I am using a filtering method that is working perfectly, but I am facing an issue where I lose my original Array when there are no dates between the specified range (as expected). Is there a way to prevent this data loss? The reason I need to r ...

Exploring Angular 4: Understanding the nuances between search and params when using http get with parameters

When working with Angular 4's HTTP package ('@angular/http'), there is an option to pass a URLSearchParams object in the get request. What sets apart using search versus params when assigning the parameters object in the request method? For ...

Creating dynamic dropdown menus within a Rails 3 form using Prototype and incorporating database queries

Recently, I've been on the hunt for a seamless method to create dynamic dropdown menus within a form that can be populated with data from a database based on the selection of a previous dropdown. Unfortunately, my search for a suitable Rails 3/prototy ...

Chrome compatibility problem with scroll spy feature in Bootstrap 3

Having trouble with scroll spy for boosters using the body method " data-spy="scroll". It seems to be working for some browsers like Edge and Google Chrome, but after multiple attempts, it still doesn't work for me. Even after asking friends to test i ...

Angular 2+ seems to be failing to detect and update changes in variables within the template

I have a component that includes rendering the user's name from the profile object. The corresponding part of the template looks like this: <button mat-button [matMenuTriggerFor]="userMenu" *ngIf="isAuthenticated()"> {{profile?.name} ...

Set the input of a component in Angular to determine its width

I am working on a basic angular component. Here is the code snippet: <div class="k-v-c" fxFlex fxLayout = "row" > <div class="k-c" fxFlex = "widthOfTable" > {{ key | translate }} </div> < div class="separator" > ...

Adding new elements to a div container

My goal is to populate a div element with items based on elements from an array. I need to duplicate an existing element on the page and append the new version to the div. Let me provide the code for better understanding: JavaScript: function apply(list ...

HTML5 Slideshow with Smooth Image Transitions

So, I have created an HTML5 image slideshow and it's working perfectly on my localhost. However, I am puzzled as to why there is no transition effect within the slideshow. I was expecting something like fading out the first picture and then having the ...

Create a list of items with checkboxes next to each that can be repeated using PdfMake

Incorporating pdfMake into my project, I am trying to display text next to an image and replicate this section in my docDefinition. The issue arises when I attempt to repeat this part using the following code snippet: { columns: [ { ...

Tweet button script fails to work properly when inserted via ajax loading

The following code snippet is used for Twitter integration: <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.in ...

No such module named PeopleService found in the exports - Ionic

I have been following a tutorial on Ionic called "10 Minutes with Ionic 2: Calling an API". Typescript Error Module 'C:/Users/grace/imaginemai/client/apiApp/src/providers/people-service/people-service' has no exported member 'PeopleService&a ...

Leveraging Angular OpaqueToken for Injecting Config Object Does Not Display Type Errors

When using an OpaqueToken to inject a config object into the application in Angular, I followed the documentation and was able to successfully DI the config into a component and retrieve values. However, I encountered an issue when trying to enforce type c ...