api.service.ts
import { Injectable, Inject } from '#angular/core';
import { Http, Headers } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/timeout';
import 'rxjs/add/operator/retry';
import { CacheService } from './cache.service';
import { AuthService } from '../services/auth.service';
import { CookieService } from 'angular2-cookie/core';
#Injectable()
export class ApiService {
constructor(
public _http: Http,
private _auth: AuthService,
private _cookie: CookieService,
#Inject('isBrowser') public isBrowser: boolean
) {}
get(){
console.log(this._cookie.get('Token'));//undefined
}
}
controller.component.ts
import { Component, OnInit, ChangeDetectionStrategy } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
import { ApiService } from './api.service';
import { ReviewComponent } from '../shared/+review/review.component';
import { CookieService } from 'angular2-cookie/core';
// import { ModelService } from '../shared/model/model.service';
#Component({
selector: 'mall',
templateUrl: './mall.component.html',
styleUrls:['./mall.component.css'],
providers: [ ApiService, CookieService ]
})
export class MallComponent implements OnInit {
constructor(private _api: ApiService, private route: ActivatedRoute, private _cookie: CookieService) {}
ngOnInit(){
this._cookie.get('Token');// Token => value
this._api.get(); //Token => undefined
}
}
I don't understand this behavior. The cookie exist when i access in controller directly but is undefined when i access through service.
Is there any way to access cookie through services?
using https://github.com/salemdar/angular2-cookie with angular universal.
Maybe this?
ngOnInit(){
this._cookie.put('Token', WHATEVER_TOKEN_IS);// Token => value
console.log(this._api.get('Token')); //Token => undefined
}
and then
api-service
export class ApiService {
constructor(
readonly _http: Http,
private _auth: AuthService,
private _cookie: CookieService,
#Inject('isBrowser') public isBrowser: boolean
) {}
get() {
const token = this._cookie.get('Token');
console.log(token);
return token;
}
}
This might be late, but I went through the same problem.
I was not defining the base path as "/". So what was happening is that the cookie was being set for the default path where I was.
Eg. I was at site.com/auth/
Cookie would get saved at path "/auth"
If I save a cookie like
this.cookieService.set('token', token, null, "/");
then problem is solved.
Hope this helps further devs.
It was my mistake to add CookieService in component providers which initiate a new instance of service which was causing the issue.
#Component({
selector: 'mall',
templateUrl: './mall.component.html',
styleUrls:['./mall.component.css'],
providers: [ ApiService, CookieService ] //<--- here
})
CookieService should only be imported into AppComponent(root) to make a single instance available to other components.
Related
I am trying to use Nodejs/Express as my back end for producing data from a database. I currently have an api route setup so that a database query will result in its directory. So if I visit localhost:3000/api currently I will see the following:
{"status":200,"data":[{"Issuer_Id":1,"Data_Id":2,"Data_Name":"Name 1"},{"Issuer_Id":2,"Data_Id":14,"Data_Name":"Name 2"},{"Issuer_Id":2,"Data_Id":1,"Data_Name":"Name 3"}],"message":null}
This leads me to believe I have everything setup correctly on the back end.
Now how do I get this data to display on my Angular front end?
I have been through hours of tutorials and this is what I have come up with:
nav.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../../data.service';
import { Series } from '../../data.service';
import {Observable} from 'rxjs/Rx';
#Component({
selector: 'app-fixed-nav',
templateUrl: './fixed-nav.component.html',
styleUrls: ['./fixed-nav.component.css']
})
export class FixedNavComponent implements OnInit{
serieses: Series[] ;
constructor(private dataService: DataService) {}
ngOnInit() {
this.dataService.getSeries().subscribe((serieses: Series[]) => this.serieses = serieses);
}
}
data.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from'#angular/common/http';
import { Http, Headers, RequestOptions, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/toPromise';
export class Series {
Issuer_Id: number;
Data_Id: number;
Data_Name: string;
}
#Injectable()
export class DataService {
constructor(private _http: Http) {}
getSeries(): Observable<Series[]> {
return this._http.get("http://localhost:3000/api/")
.map((res: Response) => res.json());
}
}
app.module.ts
import { Form1Module } from './modules/form1/form1.module';
import { FixedNavModule } from './modules/fixed-nav/fixed-nav.module';
import { HeaderModule } from './modules/header/header.module';
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
import { AppComponent } from './app.component';
import { HttpClientModule } from '#angular/common/http';
import { HttpModule } from '#angular/http';
import { DataService } from './data.service';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpModule,
HttpClientModule,
HeaderModule,
FixedNavModule,
Form1Module,
NgbModule.forRoot()
],
providers: [DataService],
bootstrap: [AppComponent]
})
export class AppModule { }
What do I need to enter in the nav.component.html to see the results?
Also note that when I refresh my angular page on lcoalhost:4200 I can see that the GET request is hitting the /apiu/ on the 3000 express server.
I am trying to help with best practices which might help get the intended result. I will amend this answer as we troubleshoot and hopefully arrive at the right answer.
So in your dataServices service I wanted to point out a couple things. Angular recommends we use the httpClient and not http and warn that http will soon be depreciated. I am fairly new to angular myself and have only ever used httpClient and have gotten great results so I recommend using that. I think this means that the promise that you are returned is changed too. Namely, you pust use a .pipe method inorder to use rxjs operators like map on the result. So this is what your dataService file would look like:
import { Injectable } from '#angular/core';
import { HttpClient } from'#angular/common/http';
import { Http, Headers, RequestOptions, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { map } from 'rxjs/operators';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/toPromise';
export class Series {
Issuer_Id: number;
Data_Id: number;
Data_Name: string;
}
#Injectable()
export class DataService {
constructor(private _http: HttpClient) {}
getSeries(): Observable<Series[]> {
return this._http.get<Series[]>("http://localhost:3000/api/")
.pipe(
map((res) => {
console.log(res);
return <Series[]> res
})
)
}
}
Note that I have imported map in a different rxjs/operators.
In actuality you dont even need to pipe or map the return since you have already declared the type of return in the get method of _http. HttpClient will cast the return into a Series[] for you so this one liner: return this._http.get("http://localhost:3000/api/") would work. I've written the code how it is however to console.log the return that your getting.
In the comments, could you tell me what is logged?
I am unable to correct your code I am providing my own setup Works for Me
In server.js
module.exports.SimpleMessage = 'Hello world';
Now in App.js
var backend = require('./server.js');
console.log(backend.SimpleMessage);
var data = backend.simpleMessage
In index html include App.js
<script src = '/App.js'></script>
alert(simpleMessage)
And you should get 'hello world'
I use an AuthService and an AuthGuard to log in/log out users and guard routes. The AuthService is used in the AuthGuard as well as in a LoginComponent. The AuthGuard is used to guard routes via CanActivate. When I try to run the app I get the following error:
zone.js:522 Unhandled Promise rejection: No provider for AuthService! ; Zone: angular ; Task: Promise.then ; Value: NoProviderError {__zone_symbol__error: Error: DI Error
at NoProviderError.ZoneAwareError
I have checked that the LoginComponent and AuthGuard both import the AuthService and inject it into the components via the constructor. I have also checked that the AuthService is imported into the AppModule file and added to the providers array so it can be used as a singleton service.
Edited to add code samples:
My App module contains the following:
#NgModule({
imports: [...],
providers: [..., AuthService, AuthGuard, ...],
declarations: [..., LoginComponent, EntryComponent ...],
bootstrap: [EntryComponent]
})
export class AppModule {
}
AuthGuard:
import { Injectable } from '#angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '#angular/router';
import { ApiConfig } from '../Api';
import { AuthService } from './authservice';
#Injectable()
export class AuthGuard implements CanActivate {
constructor(
private authService: AuthService,
private router: Router,
private config: ApiConfig
) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
console.log(this.isAuthenticated());
if (this.isAuthenticated()) {
if (this.config.defined) {
return true;
} else {
this.authService.setConfig();
return true;
}
} else {
this.router.navigate(['/Login']);
return false;
}
}
// Checks if user is logged in
isAuthenticated() {
return this.authService.userLoggedIn();
}
}
LoginComponent constructor:
constructor(
private router: Router,
private notifications: Notifications,
private authService: AuthService
) {}
AuthService:
import { Injectable } from '#angular/core';
import { Http, Headers, RequestOptions } from '#angular/http';
import { Router } from '#angular/router';
import { Observable } from 'rxjs/Observable';
import { ApiConfig } from '../Api';
#Injectable()
export class AuthService {
constructor(
private http: Http,
private router: Router,
private config: ApiConfig
) {
this.apiRoot = localStorage.getItem('apiRoot');
}
...
}
In your app.component class #Component({}) decoration add a line that states:
providers: [AuthService]
This creates a singleton service for that service at that level. If you wanted to provide it at a more granular level you would provide (instantiate) it at that lower level.
Please see the first couple paragraphs in this official angular 2 documentation
Turns out I didn't capitalize my AuthService import correctly in AuthGuard.....
import { AuthService } from './authservice';
should have been
import { AuthService } from './AuthService';
Note to self: imports are case sensitive
I am attempting to use Server-Side Rendering in Angular (v4) to allow for better SEO.
Things work as expected until I add resolve on my route. Adding resolve causes HTML title to retain it's initial value when viewing source.
My Module:
import {
Injectable,
ModuleWithProviders,
NgModule
} from '#angular/core';
import {
ActivatedRouteSnapshot,
Resolve,
Router,
RouterModule,
RouterStateSnapshot
} from '#angular/router';
import {
Observable
} from 'rxjs/Rx';
import {
ArticleComponent
} from './article.component';
import {
Article,
ArticlesService,
UserService,
SharedModule
} from '../shared';
#Injectable()
export class ArticleResolver implements Resolve < Article > {
constructor(
private articlesService: ArticlesService,
private router: Router,
private userService: UserService
) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): any {
return this.articlesService.get(route.params['slug'])
.catch((err) => this.router.navigateByUrl('/'));
}
}
const articleRouting: ModuleWithProviders = RouterModule.forChild([{
path: 'article/:slug',
component: ArticleComponent,
resolve: {
article: ArticleResolver
},
data: {
preload: true
}
}]);
#NgModule({
imports: [
articleRouting,
SharedModule
],
declarations: [
ArticleComponent
],
providers: [
ArticleResolver
]
}) export class ArticleModule {}
My Component:
import {
Component,
OnInit
} from '#angular/core';
import {
ActivatedRoute,
Router,
} from '#angular/router';
import {
Title,
Meta
} from '#angular/platform-browser';
import {
AppComponent
} from '../app.component';
import {
Article,
} from '../shared';
#Component({
selector: 'article-page',
templateUrl: './article.component.html'
})
export class ArticleComponent implements OnInit {
article: Article;
constructor(
private route: ActivatedRoute,
private meta: Meta,
private title: Title
) {}
ngOnInit() {
this.route.data.subscribe(
(data: {
article: Article
}) => {
this.article = data.article;
}
);
this.title.setTitle(this.article.title);
}
}
I am new to Angular SSR so any guidance is greatly appreciated.
Instead of subscribing to route data, retrieve your results from the snapshot like this:
this.route.snapshot.data['article']
You also might need to register ArticlesService in your providers for the module.
As a side note, this import:
import {
Observable
} from 'rxjs/Rx';
is an RxJS antipattern. Please use the following import instead:
import {Observable} from 'rxjs/Observable';
I found that my primary service was referencing a secondary service that was attempting to return an authentication token from window.localStorage.
Attempting to access the client storage caused Angular SSR to omit the generation of source code for my component.
Thanks #Adam_P for helping me walk through it!
I'm struggling with connecting the ActivationGuard with an UserAuthenticationService, which is returning from server if the given user is logged or not. The main problem here imo is the fact, it's coming from an asynchro request.
I've got some code, made with help from one kind user on Stack. It's made with observables.
But the problem here is that I'm getting following error, when entering the protected components:
zone.js:388 Unhandled Promise rejection: Cannot read property 'do' of undefined;
My files:
ActivationGuard.ts
import {Injectable} from '#angular/core';
import {Router, CanActivate, RouterStateSnapshot, ActivatedRouteSnapshot} from '#angular/router';
import {Observable} from 'rxjs/Observable';
import {UserAuthenticationService} from './UserAuthenticationService';
#Injectable()
export class ActivationGuard implements CanActivate {
constructor(private router: Router, private userService: UserAuthenticationService) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.userService.isUserAuthenticated
.do(success => {
if (!success) {
this.router.navigate(['/']);
}
});
}
}
UserAuthenticationService.ts
import {Injectable, OnInit} from '#angular/core';
import {Http} from '#angular/http';
import {Observable} from "rxjs/Observable";
#Injectable()
export class UserAuthenticationService implements OnInit {
public isUserAuthenticated: Observable<boolean>;
username: string = 'admin';
constructor(private http: Http) {}
ngOnInit(){
this.isUserAuthenticated = this.http.get(`http://localhost/api/auth/isLogged/${this.username}`)
.map(res => res.json())
.share();
}
}
Looking forward for any kind of help. If you have any questions let me know. Thank you.
I am trying to get data from server using http call .I am getting file not found error .here is my code
http://plnkr.co/edit/oCxrgxNlCkjVnTrhZGQA?p=preview
import { Page, NavController } from 'ionic-angular/index';
import { toDoservice } from '/TodoService'
#Page({
templateUrl:"home.html",
providers:[toDoservice]
})
export class HomePage {
private Todo: Array<Object>;
constructor(private nav: NavController,private toDoservice:ToDoservice) {
this.Todo=toDoservice.loadAllTodo();
}
YOu have done Various mistakes few of them are as mentioned here :-
todoService is not decorated with Annotation
Named of service injection is wrong in your file
You are importing your file in a wrong way.
There is no default extension are in the system.config
your Service should be like this :-
import {Http} from 'angular2/http';
import {Injectable} from 'angular2/core'
import 'rxjs/Rx';
#Injectable()
export class TodoService {
http;
constructor(private http: Http ){
console.log("hello")
}
loadAllTodo(){
return this.http.get('data.json').map(res => res.json())
}
}
here is working code of your Working Plunker
Use the same casing in class declaration and usage:
import { Page, NavController } from 'ionic-angular/index';
import { TodoService } from '/TodoService'
#Page({
templateUrl:"home.html",
providers:[TodoService]
})
export class HomePage {
private Todo: Array<Object>;
constructor(private nav: NavController,private todoservice:TodoService) {
this.Todo=todoService.loadAllTodo();
}
}