Utilizing Angular Services to Share Events and Reusing Components Multiple Times on a Page

My unique custom table is made up of multiple components, each emitting events using a shared service called TableEvent. These events are subscribed to by a class named TableTemplate, which facilitates communication among the different components of the table.

While everything functions properly when there is only one table on the page, issues arise when multiple tables are present. The events end up being triggered for all tables instead of just the one that generated the event. How can I resolve this problem?

@Injectable()
export class TableEvent {
    private sortChangeSubject: Subject<any> = new Subject();
    public sortChange = this.sortChangeSubject.asObservable();

    public sortChangeEmit($events) {
        this.sortChangeSubject.next($events);
    }
}

export abstract class TableTemplate implements OnInit, OnDestroy {

    protected constructor(public tableName: string, public options:TableConfig = {}) {
        this.tableEvent = AppInjector.get(TableEvent);
        this.subscription.add(this.sortChangeEvent());
    }

    protected sortChangeEvent() {
        return this.tableEvent.sortChange.subscribe($event => {               
            this.load($event);
        });
    }

    protected abstract setColumnDef(): ColumnDef[];

    protected abstract getDataSource(optionFilters?, optionsSort?): Observable<T>;
}

@Component({
    selector: 'app-clients',
    templateUrl: './clients.component.html',
    styleUrls: ['./clients.component.scss'],
    providers: [TableEvent]
})
export class ClientsComponent extends TableTemplate {
    protected setColumnDef(): ColumnDef[] {
        return [...];
    }

    protected getDataSource(optionFilters?, optionsSort?): Observable<Object> {
        return ...
    }
}

<!-- clients.component.html -->
<app-table
    [sortName]="'id'"
    ...
</app-table>

To further elaborate, TableTemplate should be treated as a class and not a component. Any component implementing my custom table needs to extend from TableTemplates.

When attempting to add

@Component({
  ...
  providers: [TableEvent]
})

to either ClientsComponent or TableComponent, an error message stating no providers for TableEvent is encountered.

This issue is occurring on Angular version 7.1

Answer №1

Ensuring that the TableEvent service is provided at the table component level guarantees that each table will have its own instance of the service:

@Component({
  ...
  providers: [TableEvent]
})
export class TableComponent extends TableTemplate {
  ...
}

Remove the root provider from the service definition as shown below:

@Injectable()
export class TableEvent {
  ...
}

To see a demo, check out this stackblitz.

Answer №2

It is crucial to assign a unique instance id to every component and provide the source and destination of the event to the service. Each component should then verify the destination id.

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

How can I retrieve List<T> from a Razor Page using TypeScript?

Within my ViewModel, I have an Items collection: public class ItemViewModel{ public List<Item> Items {get;set;} } In the Index.cshtml file: @if(Model.Items != null){ <li><a id="item-id-link" href="#" data-items="@Model.Items"> ...

Passing and removing array parameters in HTTP requests using Angular

I have an Array of statuses objects. Each status has a name and a boolean set to false by default. These represent checkboxes in a form with filters - when a checkbox is checked, the boolean value is set to true: const filters.statuses = [ { name ...

Troubleshooting issue with absolute paths in Vite project using React and TypeScript

I'm having trouble implementing absolute paths in a Vite react-ts project. This is how I set up the project: npm init @vitejs/app npx: installed 6 in 1.883s √ Project name: ... test-vite √ Select a framework: » react √ Select a variant: » rea ...

Adding to object properties in Typescript

My goal is to dynamically generate an object: newData = { column1: "", column2: "", column3: "", ... columnN: "" } The column names are derived from another array of objects called tableColumns, which acts as a global variable: table ...

Endlessly streaming data is requested through HTTP GET requests

I am facing an issue with my code where it requests data endlessly. The service I have retrieves data in the form of an Array of Objects. My intention is to handle all the HTTP requests, mapping, and subscriptions within the service itself. This is because ...

Starting up a pre-existing Angular project on your local machine

I am completely new to Angular and facing difficulties running an existing project on my machine. Despite conducting numerous tests and following various articles, I still cannot get the project to run. Here is the layout of my project files: I have succ ...

Jest may come across test suites, but it discreetly disregards the individual tests

Having encountered an issue with Jest testing in a Nuxt/Vue v2 project, I found that after making some changes, the tests were no longer running. The unit tests were either passing or failing initially, but suddenly stopped running altogether. ----------|- ...

How can I display options in a react autocomplete feature?

Using the autocomplete component from @material-ui/lab/autocomplete, I am trying to retrieve the title_display result in the options field. These results are being fetched from an API using axios. You can view my code here--> https://codesandbox.io/s/r ...

Encountering challenges while transitioning from ngrx version 2 to version 4, specifically related to typing in array de-structuring

The error indicates a missing comma after the action parameter in the .map. Another error pops up when hovering over DataActions.AddDataAction, displaying Tuple type '[Action, AppStore]' with length '2' cannot be assigned to tuple with ...

Ways to mandate a field to only be of type object in TypeScript

I need to design a type that includes one mandatory property and allows for any additional properties. For instance, I require all objects to have an _id property of type string. {_id: "123"} // This will meet the criteria {a: 1} // This will not work as i ...

Error encountered while exporting TypeScript module

While I am working with Angular, TypeScript, and Gulp, my module system is CommonJS. However, I encountered an error when trying to import a module into my main.ts file: Error: Cannot find external module 'modules.ts'. Here is the snippet from ...

encountering difficulties resolving dependency tree when attempting to generate a new Angular project

Today, I attempted to start a new Angular project using the command ng new <projectname>, but encountered the following error: npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: [email protected] npm ERR! Foun ...

Is there a way to customize the hover style of Material UI Select or Menu MenuItem using the theme?

The theme I designed import { createMuiTheme } from 'material-ui/styles'; export const MyTheme = createMuiTheme({ palette: { primary: { light: '#757ce8', main: '#3f50 ...

passing data through URL in Angular 7

Looking to pass a parameter in the URL while using Angular 7, to achieve a format like example.com/search/users?q=tom. Below is the syntax I am currently using in my service: public searchUsers(obj):any{ return this._http.get('example.com/s ...

Incorporating HTTP headers into Angular 6

Could someone confirm if this method is correct for adding headers to http requests in Angular 6? Upon inspecting the call through SwaggerUI, it appears that the required headers are: url -X GET --header 'Accept: application/json' --header &apo ...

Reactive Form value is not displaying in view because of FormControlName issue

I have successfully retrieved data from the database and need to pre-fill an update form with preset values. The issue I am facing is that when I add FormControlName to the input field, it removes the preset values. I have tried using setValue and patchV ...

Deliver Compressed Files following Angular CLI --Prod Configuration

After using the Angular CLI's command to minify my basic Angular app, a dist folder was generated with the project folder and minified files. However, when I run ng serve, it always serves the unminified development files, whether it's in the roo ...

What are the circumstances under which JavaScript GCP libraries return null values?

My current project involves working with GCP and Firebase using typescript. I have been utilizing the provided libraries, specifically version 8 of Firebase, and have encountered some unexpected behavior. For instance (firebase, ver. 8.10.1) import 'f ...

Addressing command problems in Angular

I am experiencing an issue with a dropdown functionality. When a user selects an option and then presses either the "Delete" or "Backspace" button on the keyboard, the value from the dropdown clears which is working correctly. However, I am attempting to i ...

Tips for showcasing the CDK table in Angular without duplicating customer IDs

My CDK table is used to display data, but I am facing an issue with duplicated data in the dataSource as shown below: [ {customerID:"56789", name: "foo", mobile: "123456"}, {customerID:"56789", name: "foo", mobile: "123456"}, {customerID:"12345", name: "f ...