I am not understanding why same code is not working from app.component which is perfectly worked in auth.guard.
I have written some code to check that user is Logged In to server or not and used canActivate in routing defined auth.guard like below
Routing
{ path: 'dashboard', component: DashboardComponent , canActivate: [AuthGuard] }
AuthGuard
import { Injectable } from '#angular/core';
import { Router, CanActivate } from '#angular/router';
import { AuthService} from './services/auth.service';
#Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService:AuthService, private router:Router) { }
canActivate(next:ActivatedRouteSnapshot, state:RouterStateSnapshot) {
return this.authService.isAuth().map(e => {
if (e) {
return true;
}
}).catch(() => {
this.router.navigate(['/login']);
return Observable.of(false);
});
}
}
It is working fine but not working in AppComponent
AppComponent
import { Component } from '#angular/core';
import { OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { AuthService } from './services/auth.service';
#Component({
moduleId: module.id,
selector: 'my-app',
templateUrl: './views/app.component.html',
styleUrls: [ './styles/app.component.css' ]
})
export class AppComponent implements OnInit{
title = 'Jiffy';
status:boolean;
swap:boolean=true;
constructor(authService:AuthService, private router:Router){
return this.authService.isAuth().map(e => {
if (e) {
return true;
}
}).catch(() => {
this.router.navigate(['/login']);
return Observable.of(false);
});
}
}
I am not understanding why it is not working here?
Error
Error: Uncaught (in promise): TypeError: Cannot read property 'isAuth'
of undefined TypeError: Cannot read property 'isAuth' of undefined at
new AppComponent
AuthService
isAuth(){
return this.http.get("/account/check")
.map(function(res){
return status=res.json().status;
});
}
Express Server with Passport
router.get('/check', function(req, res,next) {
if (req.isAuthenticated()){
return res.send({"status":true});
}
return res.send({"status":false});
});
You need to add public or private to the parameters inside the constructor if you want to get them with this inside your component.
constructor(private authService:AuthService, private router:Router)
The error is saying that authService is undefined. Have you declared AuthService as a provider in your app.module?
Related
I have a problem where when I type manually localhost:4200/create it goes on the page where i want it to go, but when I click on a link to lead me there, I get an error saying:
TypeError: Cannot read property 'unsubscribe' of undefined
at PostListComponent.ngOnDestroy
Here's my code:
header.component.html
<mat-toolbar color="primary">
<span><a routerLink="/">My Messages</a></span>
<ul>
<li><a routerLink="/create">New Post</a></li>
</ul>
</mat-toolbar>
app-routing.module.ts:
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { PostCreateComponent } from './posts/post-create/post-create.component';
import { PostListComponent } from './posts/post-list/post-list.component';
const routes: Routes = [
{path: '', component: PostListComponent},
{path: 'create', component: PostCreateComponent},
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
postlistcomponent.ts
import { Component, OnDestroy, OnInit } from '#angular/core';
import { Subscription } from 'rxjs';
import { Post } from '../posts';
import { PostsService } from '../posts.service';
#Component({
selector: 'app-post-list',
templateUrl: './post-list.component.html',
styleUrls: ['./post-list.component.css'],
})
export class PostListComponent implements OnInit, OnDestroy {
posts: Post[] = [];
private postsSub: Subscription;
constructor(public postsService: PostsService) {}
ngOnInit(): void {
this.postsService.getPosts();
this.postsService.getPostUpdateListener().subscribe((posts: Post[]) => {
this.posts = posts;
});
}
onDelete(postId: string) {
this.postsService.deletePost(postId);
}
ngOnDestroy() {
this.postsSub.unsubscribe();
}
}
Like the error says, you're calling unsubscribe on an object that doesn't exist in PostListComponent (postlist.component.ts?)
In that file, find the ngOnDestroy function and for any this.object$.unsubscribe() functions, test for the object first -
if (this.object$ && !this.object$.closed) {
this.object$.unsubscribe()
}
I'm using this.object$ as an example - your variable will be called something different
When you navigate from / to /create your ngOnDestroy in the PostListComponent is throwing an error.
This is why it is happening on the link and not when you put in the url.
As you can see in your ngInit you are not passing any value to your variable (postsSub). That is why you cannot destroy it.
Change this :
ngOnInit(): void {
this.postsService.getPosts();
this.postsService.getPostUpdateListener().subscribe((posts: Post[]) => {
this.posts = posts;
});
}
For this:
ngOnInit(): void {
this.postsService.getPosts();
this.postsSub = this.postsService.getPostUpdateListener().subscribe((posts: Post[]) => {
this.posts = posts;
});
}
That should work.
Regards
I am trying to use angular routing to route to a new url when a button is clicked. I also need to use the module HttpClient to call some calls to the backend. However, whenever I create a HttpClient object, the routing doesn't work and it routes to a blank page with no url extension. When I delete the object, the routing works again. Anyone know how to overcome this? Here are some of my code snippets.
agent-page-component.ts (I create a Agent Service in the constructor)
import { Router} from "#angular/router";
import { Agent } from '../../models/agent.model'
import { AgentService } from '../../services/agent.service';
import { Subject, Subscription } from 'rxjs';
#Component({
selector: 'app-agent-page',
templateUrl: './agent-page.component.html',
styleUrls: ['./agent-page.component.css']
})
export class AgentPageComponent implements OnInit {
agents: Agent[] = [];
private agentSub: Subscription;
constructor(private agentService: AgentService){}
ngOnInit() {
this.agentService.getAgents();
this.agentSub = this.agentService.getAgentUpdateListener().subscribe((agents: Agent[]) => {
this.agents = agents;
});
}
ngOnDestroy() {
this.agentSub.unsubscribe();
}
}
agent.service.ts (this is where I import an HttpClient)
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs';
import { HttpClient, HttpClientModule } from '#angular/common/http';
#Injectable({providedIn: 'root'})
export class AgentService {
private agents: Agent[] = [];
private agentsUpdated = new Subject<Agent[]>();
constructor(private http: HttpClient){}
getAgentUpdateListener() {
return this.agentsUpdated.asObservable();
}
getAgents(){
this.http.get<{message: string, agents: Agent[]}>('http://localhost:3000/agents/Breach').subscribe((agentList) => {
this.agents = agentList.agents;
})
}
}
app-routing.module.ts
import { Routes, RouterModule } from '#angular/router';
import { AgentPageComponent } from './components/agent-page/agent-page.component';
import { HomePageComponent } from './components/home-page/home-page.component';
const routes: Routes = [
{path: 'agents', component: AgentPageComponent},
{path: '', component: HomePageComponent}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
I am trying to extend some components with another class but I got
[Angular] Can't resolve all parameters for MyProjectsComponent in 'pathtomyproject'/src/app/my-projects/my-projects.component.ts: ([object Object], ?).
security.ts
import { Router} from '#angular/router';
export abstract class Security {
constructor(
protected router: Router
) { }
isLogged() {
if (!sessionStorage.getItem('user')) {
this.router.navigate(['/login']);
}
}
}
my-projects.component
import { Component, OnInit } from '#angular/core';
import { RouterModule, Router, ActivatedRoute } from '#angular/router';
import { ProjectService } from './project.service';
import { Security } from '../security';
#Component({
selector: 'app-my-projects',
templateUrl: './my-projects.component.html',
styleUrls: ['./my-projects.component.scss'],
providers: [ProjectService],
})
export class MyProjectsComponent extends Security implements OnInit {
projects: Array<any>;
constructor(
private projectService: ProjectService,
protected router
) {
super(router);
}
ngOnInit() {
this.getProjects();
}
async getProjects() {
const data: any = await this.projectService.getAll();
this.projects = data._embedded.projects;
}
delete(id) {
this.projectService.delete(id);
this.getProjects();
}
edit(id) {
const path = `/edit/${id}`;
this.router.navigate([path]);
}
}
There might be some issue in the constructor of the MyProjectsComponent. You misconfigured the dependency injection of the router. Change it to:
constructor(
private projectService: ProjectService,
protected router: Router // <-- DI for Router
) {
super(router);
}
and then it should work.
I tried to reproduce your issue in this stackblitz:
https://stackblitz.com/edit/angular-aifdew
Hi i'm new in Angular 4 and I want to use it to build a WordPress theme using the wp-api. I start with the ng-wp-theme but I and all its working fine, but I need that hen a new post is publish the post list page updates itself without reload the page. I saw some tutorials about the http services in angular but I dont find any solution to this, maybe its a Wordpress api issue and not the Angular part.
here is the service:
import { Injectable } from '#angular/core';
import { HttpClient } from "#angular/common/http";
import { Observable } from 'rxjs/Observable';
import { Post } from './post';
import { environment } from '../../environments/environment';
#Injectable()
export class PostsService {
private _wpBase = environment.wpBase;
constructor(private http: HttpClient) { }
getPosts(): Observable<Post[]> {
return this.http.get<Post[]>(this._wpBase + 'posts');
}
getPost(slug: string): Observable<Post[]> {
return this.http.get<Post[]>(this._wpBase + `posts?slug=${slug}`);
}
}
and the controller:
import { Component, OnInit } from '#angular/core';
import { Post } from '../post';
import { PostsService } from '../posts.service';
import { Router } from '#angular/router';
import { HttpErrorResponse } from '#angular/common/http';
#Component({
selector: 'app-post-list',
templateUrl: './post-list.component.html',
styleUrls: ['./post-list.component.css'],
providers: [PostsService]
})
export class PostListComponent implements OnInit {
public posts: Post[];
constructor( private postsService: PostsService, private router: Router ) {}
ngOnInit() {
this.postsService.getPosts().subscribe(
(posts: Post[]) => this.posts = posts,
(err: HttpErrorResponse) => err.error instanceof Error ? console.log('An error occurred:', err.error.message) : console.log(`Backend returned code ${err.status}, body was: ${err.error}`));
}
selectPost(slug) {
this.router.navigate([slug]);
}
}
I want to show a snackbar when my login fails that says 'error connecting'. That much is simple. But then I would like it to try again either after 10 seconds when it is dismissed or after the action dismisses the snackbar. But my observable runs immediately and I am stuck in an infinite observable loop trying to login immediately after it has failed.
login.page.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { UserService, HelpersService, AuthService } from '../../services/';
#Component({
selector: 'login-page',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss']
})
export class LoginPage {
loginError: any;
constructor(
private router: Router,
private auth: AuthService,
public helpers: HelpersService,
) { }
login() {
this.auth.login().then((response) => {
this.router.navigate(['/']);
}).catch(error => {
this.loginError = this.helpers.notify('error connecting', 'try again', 10000);
this.helpers.notifyAction(this.loginError, this.login());
});
};
}
helpers.service.ts
import { Injectable } from '#angular/core';
import { MdSnackBar, MdSnackBarRef } from '#angular/material';
#Injectable()
export class HelpersService {
constructor(public snackBar: MdSnackBar) {}
notify(message: string, action: string, duration: number) {
return this.snackBar.open(message, action, {duration});
}
notifyAction(notification: MdSnackBarRef<any>, next) {
return notification.onAction().subscribe(() => next);
}
}
You were almost there. Please pay attention to my comments in your sources.
login.page.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { UserService, HelpersService, AuthService } from '../../services/';
#Component({
selector: 'login-page',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss']
})
export class LoginPage {
loginError: any;
constructor(
private router: Router,
private auth: AuthService,
public helpers: HelpersService,
) { }
login() {
this.auth.login().then((response) => {
this.router.navigate(['/']);
}).catch(error => {
this.loginError = this.helpers.notify('error connecting', 'try again', 10000);
this.helpers.notifyAction(this.loginError, this.login); // no parenthesis here!
});
};
}
helpers.service.ts
import { Injectable } from '#angular/core';
import { MdSnackBar, MdSnackBarRef } from '#angular/material';
#Injectable()
export class HelpersService {
constructor(public snackBar: MdSnackBar) {}
notify(message: string, action: string, duration: number) {
return this.snackBar.open(message, action, {duration});
}
notifyAction(notification: MdSnackBarRef<any>, next) {
return notification.onAction().subscribe(() => next()); // they are here!
}
}
Live Example Infinity Login
You need to pass function instead of calling it. And also take care about context by using arrow function or bind.
login.page.ts
this.helpers.notifyAction(this.loginError, () => this.login());
helpers.service.ts
notifyAction(notification: MdSnackBarRef<any>, next) {
notification.afterDismissed().subscribe(next);
return notification.onAction().subscribe(notification.dismiss);
}