Angular 4: Cannot instantiate cyclic dependency! InjectionToken_HTTP_INTERCEPTORS - javascript

I know, this question may sound duplicate and I have tried everything found on stackover flow unable to resolve this problem, so please bear with me
To make you able to reproduce the error I am providing you the whole code thought this
Github Repo
Problem
I am getting the following error:
Provider parse errors:↵Cannot instantiate cyclic dependency!
InjectionToken_HTTP_INTERCEPTORS ("[ERROR ->]"): in NgModule AppModule
in ./AppModule#-1:-1
Information about the scenario (Notes)
Note 1
File: response-interceptor.service.ts
Path: ./src/app/shared/interceptors/response-interceptor/
I am intercepting the HTTPClient responses to check the 401 error and when the error comes I need to ask user to re-login.
To show the re-login prompt to user I have made a global-functions-services that has a function 'relogin'
Note 2
File: global-function.service.ts
Path: ./src/app/shared/services/helper-services/global-function/
Here is the place where this all started to happen...
As soon as I am injecting the PersonService
constructor(
public dialog: MatDialog,
private _personService: PersonService
) { }
I am getting this error and in PersonService I cannot find any import that can cause the issue.
PersonService:
./src/app/shared/services/api-services/person/person.service.ts
import { IRequest } from './../../../interfaces/I-request';
import { environment } from 'environments/environment';
import { Injectable } from '#angular/core';
// for service
import 'rxjs/add/operator/map'
import 'rxjs/add/operator/toPromise';
// models
import { Person } from 'app/shared/models/person';
import { RequestFactoryService, REQUEST_TYPES } from 'app/shared/factories/request-factory/request-factory.service';
#Injectable()
export class PersonService {
private _requestService: IRequest;
constructor(
_requestFactoryService: RequestFactoryService
) {
this._requestService = _requestFactoryService.getStorage(REQUEST_TYPES.HTTP);
}
public signup(record): Promise<Person> {
let url = environment.api + 'person/public/signup';
return this._requestService.post(url, record) as Promise<Person>;;
}
public authenticate(code: string, password: string): Promise<Person> {
let url = environment.api + 'auth/signin';
let postData = {
code: code,
password: password
}
return this._requestService.post(url, postData) as Promise<Person>;
}
}
Request
Please suggest a solution for this, I have already wasted 2 days to figure out the issue but no luck.
Many thanks!! in advance

Cyclic dependency, means circling around endless, like planets orbiting sun..
Solution: Break the dependency chain, Re-factor code.
You have GlobalFunctionService -> PersonService -> so on... -> ResponseInterceptorService -> and back to -> GlobalFunctionService.
Cycle complete.
REMOVE the PersonService dependency from GlobalFunctionService. (its not used anyway, if you need it then find different way to get around.)
import { PersonService } from 'app/shared/services/api-services/person/person.service';
import { Injectable } from '#angular/core';
import { InputModalComponent } from 'app/shared/components/input-modal/input-modal.component';
import { MatDialog } from '#angular/material';
#Injectable()
export class GlobalFunctionService {
constructor(
public dialog: MatDialog
) { }
relogin(): void {
let dialogRef = this.dialog.open(InputModalComponent, {
width: '250px',
data: { title: "Please provide your password to re-login." }
});
dialogRef.afterClosed().subscribe(result => {
debugger
console.log('The dialog was closed');
let password = result;
});
}
}

Use setTimeout() function in constructor to assign service.
constructor(private injector: Injector) {
setTimeout(() => {
this.loginService = this.injector.get(LoginService);
})
}
Try this and revert back if you face any issue.

You have to modify your response-interceptor.service.ts
import { Injectable,Inject, Injector } from '#angular/core';
constructor( inj: Injector) {
this._globalFunctionService=inj.get(GlobalFunctionService)
}
You can get more info From this link

Related

User is undefined on the context.switchToHttp().getRequest() nestjs

I'm new to nestJs and I needed to add role based access to the application so I followed the documentation but in the execution context user doesn't exist. I can't seems to find the problem here's the github repo if you need to seem more code: https://github.com/anjula-sack/slinc-backend
roles.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '#nestjs/common';
import { Reflector } from '#nestjs/core';
import { ROLES_KEY } from 'src/decorators/roles.decorator';
import Role from 'src/util/enums/role.enum';
#Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [
context.getHandler(),
context.getClass(),
]);
if (!requiredRoles) {
return true;
}
const { user } = context.switchToHttp().getRequest();
console.log(context.switchToHttp().getRequest().req);
return requiredRoles.some((role) => user.type === role);
}
}
app.controller.ts
#UseGuards(JwtAuthGuard, RolesGuard)
#Get('me/business')
#Roles(Role.ADMIN)
getBusiness(#Request() req) {
return this.usersService.getUserBusiness(req.user.id);
}
From the code, I think you are mixing global and local guard
In app.module.ts, the below code is for registering global guard.
and app.useGlobalGuard() should be used together if you want to apply guard globally.
// Remove the following code in app.module.ts
{
provide: APP_GUARD,
useClass: RolesGuard,
}
But your intention should be building a local role guard, so please remove the above code and the request user will work.

Extracting data from model to variables

I'm new to typescript and angular and I was trying to fetch some data from firebase using angularfire2 and assign it to variables to use in some other functions later. I'm only familiar with javascript dot notation where I access members of the object using dot notation seems like it doesn't work with angular can somebody please help me with extracting data from the model to variables, please
I'm still having a hard time understanding Observable and subscribes too.
code
model
export class Reacts {
sad?: number;
happy?: number;
neutral?: number;
}
service
import { Injectable } from "#angular/core";
import {
AngularFirestore,
AngularFirestoreCollection,
AngularFirestoreDocument
} from "angularfire2/firestore";
import { Reacts } from "../models/reacts";
import { Observable } from "rxjs";
#Injectable({
providedIn: "root"
})
export class ReactService {
mapCollection: AngularFirestoreCollection<Reacts>;
reacts: Observable<Reacts[]>;
constructor(public afs: AngularFirestoreDocument) {
this.reacts = this.afs.collection("reacts").valueChanges();
}
getItems() {
return this.reacts;
}
}
component
import { Component, OnInit } from "#angular/core";
import { Reacts } from 'src/app/models/reacts';
import { ReactService } from 'src/app/services/react.service';
#Component({
selector: "app-reacts",
templateUrl: "./reacts.component.html",
styleUrls: ["./reacts.component.css"]
})
export class ReactsComponent implements OnInit {
react: Reacts[];
happy: number;
sad: number;
neutral:number;
constructor(private reactsService: ReactService ) {}
ngOnInit(): void {
this.reactsService.getItems().subscribe(reacts => {
this.react = reacts;
console.log(reacts); //this works print an array object of data from database
this.happy= reacts.happy// what i'm trying to achieve
});
}
}
Ok, I'll break it down for you. You are trying to access .happy but it is actually an array of React[]
ngOnInit(): void {
this.reactsService.getItems().subscribe((reacts:Reacts[]) => { // Note I have defined its model type
this.react = reacts;
console.log(reacts); //this works print an array object of data from database
//this.happy= reacts.happy // Now VS code will show you error itself
this.happy = reacts[0].happy;
});
}
The power of typscript comes as it is strongly typed language. If you'll make changes as below in service, the VS Code will itself explain you the error:
export class ReactService {
mapCollection: AngularFirestoreCollection<Reacts>;
reacts: Observable<Reacts[]>;
constructor(public afs: AngularFirestoreDocument) {
this.reacts = this.afs.collection("reacts").valueChanges();
}
getItems(): Observable<Reacts[]> { // added return type
return this.reacts;
}
}
Once I provide return type of getItems() , you dont even have to define type in .subscribe((reacts:Reacts[]) as I have done in your component.

Recognize Back/Forward browser buttons in Angular2

I am programming an Angular2 application and I want to handle the back and forward button from the browser.
The idea is to write in the console a message on "back" click and different message on "forward" click.
I used this code:
import { Location } from '#angular/common';
export class AppComponent implements OnInit {
constructor(private location: Location) {}
ngOnInit() {
this.location.subscribe(x => { [custom message] });
}
}
The Problem is: I cannot recognize the click if it is back or forward to write the correct message in the console.
How can I check it in angular2? I don't know what should I exactly search on google. All the answers were about to handle the event but to differentiate it.
P.S. it works for me if it is in javascript.
Thank you.
I needed to differentiate between back and forward buttons in Angular (5) also, in my case for animating route transitions. I couldn't find a solution, so here's one I came up with.
Add the following to a service.
private popState: boolean = false;
private urlHistory: string[] = [];
private popSubject: Subject<boolean> = new Subject();
constructor(private location: Location, private router: Router) {
location.subscribe(event => {
let fwd = false;
if (this.urlHistory.lastIndexOf(event.url)) {
this.urlHistory.push(event.url);
}
else {
fwd = true;
this.urlHistory.pop();
}
this.popState = true;
this.popSubject.next(fwd);
})
router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
if (!this.popState)
this.urlHistory = [this.router.url];
this.popState = false;
}
})
}
get popEvent$() {
return this.popSubject.asObservable();
}
Imports:
import { Location } from '#angular/common';
import { NavigationEnd, Router } from '#angular/router';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
Remove popSubject and popEvent$ if you don't need to listen for the event externally.

NodeJS, Angular 2 | Executing method on Observable next

I'm currently getting started with Angular 2 and got stuck on something probably pretty simple:
I have a shared service chatMessageService.ts:
import { Injectable } from '#angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable()
export class ChatMessageService {
private messageList = new BehaviorSubject<string>("");
currentMessage = this.messageList.asObservable();
constructor() {
}
public addMessage(msg:string) {
this.messageList.next(msg) }
}
The service is imported by two components, one that calls it's addMessage function to add the message to the Observable and then my chatComponent.ts looks like this (shortened fpr convinience):
import { Component } from '#angular/core';
import { Message } from './message';
import { ChatMessageService } from './chatMessage.service';
#Component({
selector: 'app-chat',
templateUrl: './chat.component.html',
styleUrls: ['./chat.component.css']
})
export class ChatComponent {
conversation: Message[] = [];
//.....
constructor(private chatMessageService: ChatMessageService) { }
addUserMessage(message) {
this.conversation.push({
content: message
});
}
ngOnInit() {
this.chatMessageService.currentMessage.subscribe(message => {this.addUserMessage(message);} )
}
}
My crisis arises at that last subscripion part. When I replace
{this.addUserMessage(message);}
with
{console.log(message)}
the message is printed out perfectly fine. If I call the addUserMessage()-method manually it works just fine. But when I call the method right there, with the message as argument, nothing happens. The method isn't even executed?
Thankful for your insights!
It looks like you need some buffering in the service.
Instead of BehaviorSubject, try
private messageList = new ReplaySubject<string>(10);
See working example: Plunker

Property 'x' is private and only accessible within class 'y'

I have this piece of code:
import { Component } from '#angular/core';
import { NavController, Loading, Alert } from 'ionic-angular';
#Component({
templateUrl: 'build/pages/search/search.html',
})
export class SearchPage {
constructor (....)
{
// code here
}
findItems()
{
let loading = Loading.create({
content: "Finding items..."
});
this.nav.present(loading);
// other stuff here
}
When I run ionic serve everything shows correctly but when I click a button which calls findItems() method I get this error:
Error TS2341: Property 'create' is private and only accessible within class 'Loading
An analogous errors appears if I do:
let alert = Alert.create({
title: 'Hello!',
});
In this case in my terminal appears following message:Error TS2341: Property 'create' is private and only accessible within class 'Alert'.
I'm working with Ionic2 version 2.0.0-beta.36
EDIT: This only applies to beta 11 and higher
This is because create is a private function of the class Loading, and therefore not callable outside of the Loading class.
The code example from Ionic's documentation shows a LoadingController class used to instantiate the Loading object with the desired options. I would start there.
import { LoadingController } from 'ionic-angular';
//...
constructor(private loadingController: LoadingController) {
}
findItems() {
let loading = this.loadingController.create({
content: "Finding items..."
duration: 3000
});
loading.present();
// other stuff here
}
It looks like the syntax for Alerts has changed. Here's the new syntax:
import { AlertController } from 'ionic-angular';
export class MyPage {
constructor(private alertController: AlertController){
}
showAlert() {
let alert = this.alertController.create({
title: 'New Friend!',
subTitle: 'Your friend, Obi wan Kenobi, just accepted your friend request!',
buttons: ['OK']
});
alert.present();
}
}

Categories