Can classes be encapsulated within a NgModule in Angular 2/4?

Looking to organize my classes by creating a module where I can easily import them like a separate package. Take a look at this example:

human.ts (my class file)

export class Human {

  private numOfLegs: Number;

  constructor() {
    this.numOfLegs = 2;
  }
}

test.module.ts (my module file)

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { Human } from './human';

@NgModule({
  imports: [CommonModule],
  declarations: [
    Human
  ],
  providers: [],
  exports: [Human]
})
export class TestModule {}

Now, how do I create an instance of the Human class in a component? I've attempted importing it with both methods:

import { TestModule } from './test.module';

and

import { Human } from './test.module';

However, when trying new Human(), I encounter the error message "cannot find name Human". Any guidance on this issue would be greatly appreciated.

Answer №1

Angular modules and ES6 / TypeScript / Node modules have distinct differences. Angular modules consist of Components, Services, and Directives, while ES6 modules typically involve classes.

To reuse your NgModule that relies on other non-Angular classes, you can export them as ES6 modules for use elsewhere. Create a file like export.ts or index.ts and include the necessary export statements -

export { TestModule } from './test.module';
export { Human } from './human';

When you need to utilize the NgModule in another location, import it using a command similar to the following -

import { TestModule } from '../lib/export'; 

Answer №2

It's important to note that providing a class in the declarations or exports section is not recommended. These sections are specifically for components, directives, and pipes, so adding a Human class there would be a mistake.

One option is to provide Human as a value provider instead of a class provider in the module. This means that it needs to be instantiated manually. This approach is ideal when a class requires non-DI arguments.

@NgModule({
  providers: [{ provide: Human, useValue: Human }]
})
export class TestModule {}

...

import { Human } from '...';

@Component(...)
class SomeComponent {
  constructor(@Inject(Human) human: typeof Human) {
    this.human = new Human();
  }
}

Alternatively, you can make Human a component provider. This will result in it being instantiated for each instance of the component. In this scenario, using TestModule becomes unnecessary. This method is typically preferred:

import { Human } from '...';

@Component({ providers: [Human], ... })
class SomeComponent {
  constructor(public human: Human) {}
}

In either case, remember to import the Human DI token in the component file where it's being used.

Answer №3

Transform the Human class into an injectable and define it in the providers section of your testing module.

If your main app module eagerly loads the testing module, the providers specified in the testing module will be accessible in the app module, allowing you to inject Human into components from the root module.

The scenario changes if you opt for lazy loading of the testing module - in this case, they operate with their unique injectors and do not exchange providers with other modules.

@NgModule({
  imports: [CommonModule],
  providers: [Human]
})
export class TestModule {}

Assuming that you load the TestModule via router configuration:

@NgModule({
  imports: [ BrowserModule, TestModule,
    RouterModule.forRoot([
      {path: 'test', loadChildren: TestModule},
      )
  ],
    bootstrap:    [ AppComponent ]
})

In the AppComponent, you can now inject Human:

export class AppComponent {

  constructor(human: Human) {
    console.log(human.numOfLegs);
  }
}

Ensure that numOfLegs is set as public.

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 method for saving console.log output to a file?

I have a tree structure containing objects: let tree = {id: 1, children: [{id: 2, children: [{id: 3}]}]} My goal is to save all the id values from this tree in a text file, indenting elements with children: 1 2 3 Currently, I am using the following ...

Angular2 Uniqueness Validator: Ensuring Data Integrity

Within my Angular2 form field, I am trying to ensure that the inputted value does not already exist. The challenge lies in accessing instance members within my custom validator function, codeUnique(). Upon execution, "this" refers to either FormControl o ...

What is the best way to connect an event in Angular 2?

This is an input label. <input type="text" (blur) = "obj.action"/> The obj is an object from the corresponding component, obj.action = preCheck($event). A function in the same component, preCheck(input: any) { code ....}, is being used. Will it wor ...

Using Angular Project: Exploring the Feasibility of Accessing SCSS Files from Node_modules in Custom Components

When setting up Angular, how can I include a Bootstrap SCSS file in a Custom Component using Style.SCSS? In Angular.json { "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "p ...

How can I store unique and only selected checkbox values in an array using Angular?

I need assistance with creating an array from three checkboxes. The array should only contain the values of the checked checkboxes and should not include duplicates. I have attempted to achieve this functionality, but the values are still being added rega ...

Tips for troubleshooting the 404 error on nginx servers

I've got an angular 4 Single Page Application (SPA) and I'm using Docker for production. Everything seems to be going smoothly so far. When I navigate to the /dist folder in the terminal, I use the following command to point docker to the content ...

Navigating through Angular Material table elements

Currently, I am working with Angular Material's mat-table component and have noticed a unique notation used for loop properties such as *matCellDef, which is demonstrated in this Demo. In an attempt to streamline my code, I sought to dynamically gener ...

Error: Firebase has encountered a network AuthError, which could be due to a timeout, interrupted connection, or an unreachable host. Please try again later. (auth/network-request-failed

I have set up my Angular app to utilize Firebase's emulators by following the instructions provided in this helpful guide. In my app.module.ts, I made the necessary configurations as shown below: import { USE_EMULATOR as USE_AUTH_EMULATOR } from &apos ...

Is there a way to configure the currency symbols in App.module for GYD (Guyana Dollar) since the Angular Currency Pipe Symbol is not available for it

<h1> My current rate is : {{'202' | currency:'GYD'}}</h1>` The current output displays as: GYD 202 However, the expected output should be: GY$ 202 ...

Errors encountered when attempting to update Angular from version 5 to version 6

After following the update guide, I encountered some errors that I am unsure about. https://i.stack.imgur.com/jc65s.jpg To resolve the issues, some have recommended installing rxjs-compat, but unfortunately, this only led to more errors: https://i.stack ...

Customize PrimeNG component styles

Utilizing the PrimeNG OverlayPanel for a dropdown click feature, I am encountering an issue with moving the default left arrow to the right position. Despite trying various solutions, I have reached a dead end. Would you be able to provide me with some fr ...

Tips for customizing Material UI's styled() SVG icon to accept SVG icon as a react component:

Currently, I have functioning code that uses the "any" type for props. When transitioning to MUI v5 and using the mui v4 makeStyles, this approach raises compatibility issues that were not present before. // Import SVG Icons components import { ReactCo ...

Running a method at any given time within an ngFor loop in Angular 5

On my angular page, I am facing a challenge with updating a variable and displaying it in the HTML within an *ngFor loop. Here is an example of what I need: HTML: <table *ngFor="let data of Dataset"> somehowRunThis(data) <div>{{meth ...

A guide to effectively unit testing StripeJs within the Karma testing framework for Angular 8

I'm currently facing a challenge in unit testing a payment component that relies on StripeJS. In my 'ng-app.js' file, I import it as follows: stripe: /*@ngInject*/ function ($ocLazyLoad) { return $ocLazyLoad.load({ ...

The argument type 'MatSort | null' cannot be assigned to the parameter type 'MatSort' in this scenario

When attempting to retrieve sorted data from MatTableDataSource, I used the following code: this.source = this.dataSource.sortData(this.dataSource.filteredData,this.dataSource.sort); Unfortunately, I encountered an error message: Argument of type ' ...

Is there an automatic bottom padding feature?

Currently, I am facing a challenge in fitting the loader into the container without it being overridden by the browser. Using padding-bottom is not an ideal solution as it results in the loader appearing un-resized and unprofessional. Any suggestions or co ...

Identifying whether a particular area is represented in a geographic map array presents a significant challenge

Having an issue with typescript currently. I have a variable that contains different string entries representing x, y positions. The entries are as follows: ["3,3","3,4","3,5","2,3","2,4","2,5","-1,-2","-2,- 2","-2,-1"] My goal is to determine if this land ...

`The error "mockResolvedValue is not recognized as a function when using partial mocks in Jest with Typescript

Currently, I am attempting to partially mock a module and customize the return value for the mocked method in specific tests. An error is being thrown by Jest: The error message states: "mockedEDSM.getSystemValue.mockResolvedValue is not a function TypeEr ...

The error message indicated that a Promise<string> was expected, but instead a Promise<string|number> was received

Confusion Over Promise Type Error How did the TypeScript compiler generate the error message displaying Type Promise <string|number> ... in the following scenario? Type 'Promise<string | number>' is not assignable to type 'Prom ...

Tips for creating an HTTP only cookie in NestJS

Currently, I am in the process of incorporating JWT authorization with both an accessToken and refreshToken. The requirement is to store these tokens in HTTP-only cookies. Despite attempting this code snippet, I have encountered an issue where the cookies ...