Angular 9: Cannot instantiate cyclic dependency - html

I am reusing a service for HTTP communication which worked fine under Angular 8, but throws the following error under Angular 9:
Error: Cannot instantiate cyclic dependency! HttpService
at throwCyclicDependencyError (core.js:8122)
at R3Injector.hydrate (core.js:17206)
at R3Injector.get (core.js:16960)
at NgModuleRef$1.get (core.js:36337)
at Object.get (core.js:33981)
at getOrCreateInjectable (core.js:5880)
at Module.ɵɵdirectiveInject (core.js:21115)
at NodeInjectorFactory.DashboardComponent_Factory [as factory] (dashboard.component.ts:9)
at getNodeInjectable (core.js:6025)
at instantiateRootComponent (core.js:12788)
at resolvePromise (zone-evergreen.js:798)
at resolvePromise (zone-evergreen.js:750)
at zone-evergreen.js:860
at ZoneDelegate.invokeTask (zone-evergreen.js:399)
at Object.onInvokeTask (core.js:41640)
at ZoneDelegate.invokeTask (zone-evergreen.js:398)
at Zone.runTask (zone-evergreen.js:167)
at drainMicroTaskQueue (zone-evergreen.js:569)
at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:484)
at invokeTask (zone-evergreen.js:1621)
This is the code of the HTTP service:
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
#Injectable()
export class HttpService {
url: string = 'http://localhost:8000/';
constructor(private httpClient: HttpClient) { }
public getTestCall() {
return this.httpClient.get(this.url + 'test');
}
}
This is one of the components using HTTP service:
import { Component, OnInit } from '#angular/core';
import { HttpService } from 'src/app/services/http.service';
#Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit {
constructor(private http: HttpService) { }
ngOnInit(): void { }
}
This is my app.module.ts:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpService } from './services/http.service';
import { environment } from 'src/environments/environment';
import { DashboardComponent } from './views/dashboard/dashboard.component';
import { MaterialsComponent } from './views/materials/materials.component';
import { OrdersComponent } from './views/orders/orders.component';
import { CustomersComponent } from './views/customers/customers.component';
import { ModelsComponent } from './views/models/models.component';
import { ProductsComponent } from './views/products/products.component';
import { HttpClientModule } from '#angular/common/http';
#NgModule({
declarations: [
AppComponent,
DashboardComponent,
MaterialsComponent,
OrdersComponent,
CustomersComponent,
ModelsComponent,
ProductsComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [
HttpService,
{ provide: 'BACKEND_API_URL', useValue: environment.backendApiUrl }
],
bootstrap: [AppComponent]
})
export class AppModule { }
The components are referred within the app.component.html using the [routerLink] directive and app-routing.module.ts
Thanks in advance!

I prefer declaring the HTTP Services as:
#Injectable({
providedIn: 'root',
}) and not providing them in any module.
That way the Service is accessible on the whole app from the beginning and probably you won't have error like this.
It would be better If you include your apps modules in the question.

If you have more than one modules:
The problem could be, that the HttpService is provided in more than one of your modules.
In that case:
Solution can be to create a new module: HttpServiceModule:
#NgModule({
providers: [ HttpService ]
})
export class HttpServiceModule {}
After that, you have to delete in all other modules: providers: [ ...HttpService... ]

Related

Angular - Can't import a component from a library

I'm learning Angular and I decided to create separate generic elements in addition to the main project (in a library) and then import and use them according to my needs.
My problem is due to the fact that I can't import the generic components now... (I can import the Module from the library, but when I try to use my component's selector, Angular warns that the element is unknown to it and doesn't compile the server ).
Generic Component:
(.html)
<p>f-base-screen works!</p>
(.ts)
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'nx-flow-base-screen',
templateUrl: './f-base-screen.component.html',
styleUrls: ['./f-base-screen.component.scss'],
})
export class FBaseScreenComponent implements OnInit {
constructor() {}
ngOnInit(): void {}
}
Library Module:
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { FBaseScreenComponent } from './f-base-screen/f-base-screen.component';
#NgModule({
imports: [
CommonModule
],
declarations: [
FBaseScreenComponent
],
exports: [
FBaseScreenComponent
],
})
export class FLibrariesModule {}
f-libraries.ts (exports the module and its components):
export * from './f-libraries.module';
export * from './f-base-screen/f-base-screen.component';
My SharedModule (it's later imported into my app.module):
import { CommonModule } from "#angular/common";
import { NgModule } from "#angular/core";
import { FLibrariesModule } from "#nx-flow/f-libraries";
#NgModule({
imports: [CommonModule, FLibrariesModule],
exports: [CommonModule, FLibrariesModule],
providers: []
})
export class SharedModule {}
App.module.ts:
import { NgModule } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
import { BrowserModule } from '#angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FRestService } from './shared/utils/rest.service';
import { SharedModule } from './shared/shared.module';
#NgModule({
declarations: [AppComponent],
imports: [BrowserModule, AppRoutingModule, HttpClientModule, SharedModule],
exports: [],
providers: [FRestService],
bootstrap: [AppComponent],
})
export class AppModule {}
My Home.component.module.ts (which imports the SharedModule to use the nx-flow-base-screen component):
import { NgModule } from '#angular/core';
import { WelcomeService } from '../../shared/services/flow-services/welcome.service';
import { SharedModule } from '../../shared/shared.module';
import { FRestService } from '../../shared/utils/rest.service';
import { HomeComponent } from './home.component';
#NgModule({
declarations: [HomeComponent],
imports: [SharedModule],
providers: [WelcomeService, FRestService],
bootstrap: [HomeComponent],
})
export class HomeComponentModule {}
My Home.component.html (using the component, the error that appears in the image is the same as angular throws when I compile):
<div>
<span>Home Page</span>
</div>
<nx-flow-base-screen></nx-flow-base-screen>
I already researched and followed tutorials, none of them worked so far. Are there any changes I still need to make to be able to use my component, from the library, within my main project?
If any more files are needed to reach a conclusion, I'll post a print of it.
Error:
apps/flow/src/app/views/home/home.component.html:4:3 - error
NG8001: 'nx-flow-base-screen' is not a known element:
If 'nx-flow-base-screen' is an Angular component, then verify that it is part of this module.
If 'nx-flow-base-screen' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component
to suppress this message.

How to use Angular components from different folder?

Seems like an obvious design decision for me but i can't seem to find any info on how to implement it.
I did the following:
created /pages folder and turned components in to modules for routing
created /components folder for components only
src/app/components/footer/footer.component.ts :
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-footer',
templateUrl: './footer.component.html',
styleUrls: ['./footer.component.css']
})
export class FooterComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
src/app/pages/home/home.component.ts :
import { Component, OnInit } from '#angular/core';
import { TranslateConfigService } from 'src/app/services/translate-config.service';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor(private translateConfigService: TranslateConfigService) { }
ngOnInit(): void {
}
}
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { RouterModule } from '#angular/router';
import { HomeRoutes } from './home.routes';
import { TranslateModule } from '#ngx-translate/core';
import { HomeComponent } from './home.component';
import { FooterComponent } from 'src/app/components/footer/footer.component';
#NgModule({
declarations: [
HomeComponent,
FooterComponent,
],
exports: [HomeComponent],
imports: [
CommonModule,
RouterModule.forChild(HomeRoutes),
TranslateModule
]
})
export class HomeModule { }
I didn't import anything explicitly, but when i try to use from /components in some page's html - i get an error saying
Error: src/app/pages/terms/terms.component.html:391:1 - error NG8001: 'app-footer' is not a known element:
1. If 'app-footer' is an Angular component, then verify that it is part of this module.
2. If 'app-footer' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.

Logout From website if user does not do any activity in our web from Last 15 minutes

how to Logout From website if user does not do any move in our web from 15 minutes?
In Your angular app
npm install --save #ng-idle/core #ng-idle/keepalive angular2-moment
Set up your application module
Open src/app/app.module.ts and import the Ng2IdleModule using
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { NgIdleKeepaliveModule } from '#ng-idle/keepalive'; // this includes the core NgIdleModule but includes keepalive providers for easy wireup
import { MomentModule } from 'angular2-moment'; // optional, provides moment-style pipes for date formatting
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
MomentModule,
NgIdleKeepaliveModule.forRoot()
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Extend your Main component
import { Component, OnInit } from '#angular/core';
import { Router, NavigationStart } from '#angular/router';
import { Idle, DEFAULT_INTERRUPTSOURCES } from '#ng-idle/core';
import { Keepalive } from '#ng-idle/keepalive';
#Component({
selector: 'app-theme',
templateUrl: './theme.component.html',
styleUrls: ['./theme.component.css']
})
export class AppComponent implements OnInit {
lastPing?: Date = null;
constructor(private route: Router, private idle: Idle, private keepalive: Keepalive) {
idle.setIdle(5);
idle.setTimeout(900);
idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);
idle.onIdleEnd.subscribe(() => { });
idle.onTimeout.subscribe(() => {
this.logout();
});
idle.onIdleStart.subscribe(() => {
});
idle.onTimeoutWarning.subscribe((countdown) => {
});
keepalive.interval(5);
keepalive.onPing.subscribe(() => this.lastPing = new Date());
this.reset();
}
ngOnInit() {
}
reset() {
this.idle.watch();
}
logout() {
//--
// LogoutCode
//---
}
}

Trying to pass JSON data with angular/nativescript routing

I'm currently working on a nativescript/angular/typescript project and I'm basically trying to pass JSON data from one view (property) to another (propertyinfo).
First, I load up a JSON file in property.service.ts:
import { Injectable } from '#angular/core';
import { HttpClientModule, HttpClient } from '#angular/common/http';
#Injectable()
export class PropertyService {
public propertyData: any;
public selectedProperty: any;
constructor(private http: HttpClient) {
this.loadProperties();
}
loadProperties() {
this.http.get('/pages/property/property.json').subscribe(
(data) => {
this.propertyData = data;
}
)
}
}
This JSON data gets displayed in a view property.component.html:
<StackLayout *ngFor="let item of propertyData" class="list-group" xstyle="height: 300">
<GridLayout rows="110" columns="*, 40" (tap)="details(item)">
<StackLayout row="0" col="0">
<Label text="{{item.streetName}} {{item.houseNumber}}" class="text-primary p-l-30 p-t-5"></Label>
<Label text="{{item.etc}} {{item.etc}}" class="text-primary p-l-30 p-t-5"></Label>
</StackLayout>
<Label row="0" col="1" text="" class="fa arrow" verticalAlignment="middle"></Label>
</GridLayout>
<StackLayout class="hr-light"></StackLayout>
Here, the (tap)="details(item)" will call a function in property.component.ts:
import { Component, OnInit } from '#angular/core';
import { Router } from "#angular/router";
import { PropertyService } from './property.service';
#Component({
selector: 'app-property',
templateUrl: 'pages/property/property.component.html',
providers: [PropertyService]
})
export class PropertyComponent implements OnInit {
public propertyData: any;
constructor(private router: Router, private propertyService: PropertyService) {}
ngOnInit() {
this.propertyData = this.propertyService.propertyData;
}
details(item: any) {
this.propertyService.selectedProperty = item;
this.router.navigate(["/propertyinfo"]);
}
}
Now, when I perform a console.log(JSON.stringify(this.propertyService.selectedProperty)); within my details function, the output is as follows:
JS: {"ID":4,"description":"Lorem ipsum dolor sit amet...", "streetName":"Somestreet","houseNumber":459,"etc":"etc"}
This is my propertyinfo.component.ts:
import { Component, OnInit } from '#angular/core';
import { PropertyService } from '../property/property.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-propertyinfo',
templateUrl: 'pages/propertyinfo/propertyinfo.component.html'
})
export class PropertyinfoComponent implements OnInit {
public selectedProperty: any;
constructor(private propertyService: PropertyService, private router: Router) {
this.selectedProperty = this.propertyService.selectedProperty;
}
ngOnInit() { }
}
Yet, when I perform a console.log(JSON.stringify(this.selectedProperty)); inside the constructor, the output is JS: undefined.
At the bottom of this post, I'll add the app.routing.ts and app.module.ts files so you can see all of my imports/directives etc. I'm really at a loss as to what I'm missing. I hope you can help me.
app.routing.ts:
import { NgModule } from "#angular/core";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { Routes } from "#angular/router";
import { PropertyComponent } from "./pages/property/property.component";
import { PropertyinfoComponent } from ".//pages/propertyinfo/propertyinfo.component";
const routes: Routes = [
{ path: "", component: PropertyComponent },
{ path: "propertyinfo", component: PropertyinfoComponent },
];
#NgModule({
imports: [NativeScriptRouterModule.forRoot(routes)],
exports: [NativeScriptRouterModule]
})
export class AppRoutingModule { }
app.module.ts:
import { NgModule, NO_ERRORS_SCHEMA } from "#angular/core";
import { NativeScriptHttpClientModule } from "nativescript-angular/http-client";
import { HttpClientModule, HttpClient } from '#angular/common/http';
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { AppRoutingModule } from "./app.routing";
import { AppComponent } from "./app.component";
import { PropertyService } from "./pages/property/property.service";
import { PropertyComponent } from "./pages/property/property.component";
import { PropertyinfoComponent } from "./pages/propertyinfo/propertyinfo.component";
#NgModule({
bootstrap: [
AppComponent
],
imports: [
NativeScriptModule,
AppRoutingModule,
NativeScriptRouterModule,
HttpClientModule,
NativeScriptHttpClientModule,
],
declarations: [
AppComponent,
PropertyComponent,
PropertyinfoComponent
],
providers: [
PropertyService
],
schemas: [
NO_ERRORS_SCHEMA
]
})
export class AppModule { }
Thank you for any help in advance. If I need to clear things up/provide any more info, please let me know.
console.log(JSON.stringify(this.selectedProperty)) returns undefined in PropertyinfoComponent because the PropertyService service being injected is not the same instance in PropertyinfoComponent than it is in PropertyComponent
you did not post the full .html for both component so I can only assume that you have something like the PropertyComponent is a parent component and has a reference/include a PropertyinfoComponent in the html and because of the way angular work, it injected a new instance of the service instead of using the one from the parent component.
check Thierry Templier answer for more information about angular service injection for this type of issue : How do I create a singleton service in Angular 2?

Angular 2 service not able to resolve all parameters

Hi I am trying this for last two days using http reading local json file ,not sure where the problem is
my service file
import {Injectable} from '#angular/core';
import { Http,Response } from '#angular/http';
import { Observable } from 'rxjs/Observable'
import 'rxjs/add/operator/map'
import 'rxjs/add/operator/catch'
export class AcquirerService{
private _url : string = "agent_output1.json";
constructor(private _http : Http){}
getAcquirer(){
return this._http.get(this._url).subscribe(
(data) => console.log(data)
)
// .map((response:Response) => response.json());
}
my component file
import { Component ,OnInit} from '#angular/core';
import {AcquirerService} from '../services/acquirer.service'
#Component({
selector : 'acquirer-message',
templateUrl: '../templates/acquirer.component.html',
providers :[AcquirerService]
})
export class AcquirerComponent implements OnInit{
acquirer_response ;
constructor(private _acquirerService : AcquirerService){
}
ngOnInit(){
this._acquirerService.getAcquirer();
// .subscribe(resAcquirerData => this.acquirer_response = resAcquirerData);
}
}
The error which i am getting is
metadata_resolver.js:972 Uncaught
SyntaxError {__zone_symbol__error: Error: Can't resolve all parameters for AcquirerService: (?)
my main.ts file
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { enableProdMode } from '#angular/core';
import { environment } from './environments/environment';
import { AppModule } from './app/app.module';
import {HttpModule} from '#angular/http'
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule);
my app module file
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpModule,JsonpModule } from '#angular/http';
import { AppComponent } from './components/app.component';
import {AcquirerComponent} from "./components/acquirer.component";
import {IssuerComponent} from "./components/issuer.component";
#NgModule({
declarations: [
AppComponent,AcquirerComponent,IssuerComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
JsonpModule
],
providers: [],
bootstrap: [AppComponent,HttpModule]
})
export class AppModule { }
any help will be much appreciated I am new to angular
Add AcquirerService into providers
#NgModule({
declarations: [
AppComponent,AcquirerComponent,IssuerComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
JsonpModule
],
providers: [AcquirerService],
bootstrap: [AppComponent,HttpModule]
})
export class AppModule { }
plus add #Injectable() before AcquirerService
#Injectable()
export class AcquirerService{ ... }
In your service file, you imported the Injectable but didn't use it. Put #Injectable() before the service name like this
#Injectable()
export class AcquirerService{
//your code here
}