I'm trying to connect an Angular Project with a NodeJs API, the issue is that the request doesn't work on Angular side, tho it works well in console and browser.
I tried it in console like:
curl http://127.0.0.1:3333/table
And I got back the response:
[{"userid":2,"roleid":2,"username":"partner2","fullname":"His Full Name","psw":"gmail#gail.com","email":"password","balance":0}]%
I assume there are some issues on Angular side.
Would you have any idea how to fix it?
// app.modules.ts
import { BrowserAnimationsModule } from '#angular/platform-browser/animations'; // this is needed!
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
import { RouterModule } from '#angular/router';
import { AppRoutingModule } from './app.routing';
import { ComponentsModule } from './components/components.module';
import { ExamplesModule } from './examples/examples.module';
import { AppComponent } from './app.component';
import { NavbarComponent } from './shared/navbar/navbar.component';
import {HTTP_INTERCEPTORS, HttpClientModule} from '#angular/common/http';
import {AuthInterceptor} from './auth.interceptor';
import {BrowserModule} from '#angular/platform-browser';
#NgModule({
declarations: [
AppComponent,
NavbarComponent
],
imports: [
BrowserModule,
HttpClientModule,
BrowserAnimationsModule,
NgbModule,
FormsModule,
RouterModule,
AppRoutingModule,
ComponentsModule,
ExamplesModule
],
providers: [
/*{
provide : HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi : true,
},*/
],
bootstrap: [AppComponent]
})
export class AppModule { }
// services.services.ts
import { Injectable } from '#angular/core';
import {HttpClient} from '#angular/common/http';
import {Observable} from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class ServiceService {
constructor(private httpClient: HttpClient) {
}
public createNewUser(bodyParams: any): Observable<any> {
return this.httpClient.post('carriers/new-carrier', bodyParams);
}
public getTableX(): Observable<any> {
return this.httpClient.get('http://localhost:3003/api/table');
}
public getTableZ(): Observable<any> {
return this.httpClient.get('http://localhost:3003/table');
}
public getTable(): Observable<any> {
return this.httpClient.get('http://127.0.0.1:3333/table');
}
}
You should fix that issue at your packend side, browser need responses with allowed cors Cross-Origin please check https://expressjs.com/en/resources/middleware/cors.html when you are using Espress Node js.
This issue has been fixed through adding below line to my proxy
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});
https://medium.com/#dtkatz/3-ways-to-fix-the-cors-error-and-how-access-control-allow-origin-works-d97d55946d9
Related
I am a new coder with nestjs, I want to use passport-jwt , nestjs/passport and firebase to build my app's authetication part, below are my codes. But I just got http 401 response, how can i fix it ?
here is my strategy:
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '#nestjs/passport';
import { Injectable } from '#nestjs/common';
import { getAuth } from 'firebase-admin/auth';
#Injectable()
export class FirebaseStrategy extends PassportStrategy(Strategy, 'firebase') {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKeyProvider: async (request, rawJwtToken, done) => {
try {
const decodedToken = await getAuth().verifyIdToken(rawJwtToken);
done(null, decodedToken);
} catch (error) {
done(error);
}
},
});
}
async validate(payload: any) {
console.log('validate');
return payload;
}
}
here is my guard:
import { Injectable } from '#nestjs/common';
import { AuthGuard } from '#nestjs/passport';
#Injectable()
export class FirebaseAuthGuard extends AuthGuard('firebase') {}
here is my auth.module.ts:
import { Module } from '#nestjs/common';
import { AuthService } from './auth.service';
import { UsersModule } from '../users/users.module';
import { PassportModule } from '#nestjs/passport';
import { JwtModule } from '#nestjs/jwt';
import { FirebaseStrategy } from './firebase.stragety';
import { AuthController } from './auth.controller';
#Module({
controllers: [AuthController],
imports: [UsersModule, PassportModule, JwtModule.register({})],
providers: [AuthService, FirebaseStrategy],
exports: [AuthService],
})
export class AuthModule {}
and here is my controller:
import { Controller, Get, Request, UseGuards } from '#nestjs/common';
import { AuthService } from './auth.service';
import { FirebaseAuthGuard } from './firebase.guard';
#Controller('auth')
export class AuthController {
constructor(private authService: AuthService) {}
#UseGuards(FirebaseAuthGuard)
#Get('login')
async logIn(#Request() req) {
return 'login';
}
}
I just found my validate method in FirebaseStrategy not invoked, it should be invoked everytime when secretOrKeyProvider verified jwt in http header, isn't it ?
If you're getting a 401 with no call of the validate method of your JwtStrategy that means that for some reason passport is reading the JWT you send as invalid. To find the specific reason for it you can modify your FirebaseAuthGuard to have the following handleRequest method, which will log out extra details
handleRequest(err, user, info, context, status) {
console.log({ err, user, info, context, status });
return super.handleRequest(err, user, info, context, status);
}
As mentioned, this will print out what error or info passport is reading and throwing for, and will allow you to properly adjust your JWT/know to refresh it/change it because of invalid signature/whatever else.
I am able to access other endpoints from my frontend but when I want to access the socket endpoint I get this error message:
chat:1 Access to XMLHttpRequest at
'http://localhost:3000/socket.io/?EIO=3&transport=polling&t=NOAlAsz'
from origin 'http://localhost:4200' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested
resource.
chatapp.component.ts
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
import { User } from '../models/users';
import { AuthService } from '../services/auth.service';
import { SocketService } from '../services/socket/socket.service';
import { UsersService } from '../services/users/users.service';
#Component({
selector: 'app-chatapp',
templateUrl: './chatapp.component.html',
styleUrls: ['./chatapp.component.scss']
})
export class ChatappComponent implements OnInit {
private socket
chatForm:FormGroup
user:User
groups
submitted =false
constructor(
private socketService:SocketService,
private formBuilder:FormBuilder,
private userService:UsersService,private authentication:AuthService) {
this.chat()
}
ngOnInit(): void {
this.getUser()
this.getUserGroups()
}
chat(){
this.chatForm = this.formBuilder.group({
chat:['',Validators.required]
})
}
}
socket.service.ts
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';
import * as io from 'socket.io-client';
#Injectable({
providedIn: 'root'
})
export class SocketService {
private socket
private socketUrl = 'http://localhost:3000';
constructor(private http: HttpClient) {
this.socket = io(this.socketUrl)
}
}
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 { LoginComponent } from './login/login.component';
import { SignupComponent } from './signup/signup.component';
import { ChatappComponent } from './chatapp/chatapp.component';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { HttpClientModule } from '#angular/common/http';
import { SocketService } from './services/socket/socket.service';
#NgModule({
declarations: [
AppComponent,
LoginComponent,
SignupComponent,
ChatappComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule
],
providers: [SocketService],
bootstrap: [AppComponent]
})
export class AppModule { }
my backend server
app.js
const express = require('express')
const http = require('http')
const path = require('path')
const socketIO = require('socket.io')
const moment = require('moment')
const morgan = require('morgan')
const winston = require('winston')
const formateMessage = require('./utils/messages')
const formatMessage = require('./utils/messages')
const cors = require('cors')
const app = express()
app.use(morgan('tiny'))
app.use(cors())
require('./startup/db')()
require('./startup/router')(app)
app.get('',(req,res) => {
res.send({
title:'Chat-App',
})
});
const server = http.createServer(app)
const io = socketIO(server)
//Set static folder
app.use(express.static(path.join(__dirname,'public')));
const appName = "Chat-app"
io.on('connection',socket => {
socket.on('joinRoom', ({username , room }) => {
//to the single client connecting
socket.emit('message',formateMessage(appName,'Welcome to chat-app!'));
//Broadcast when a user connected to all users except that particular user that connected
socket.broadcast.emit('message',formateMessage(appName,'A user has joined the chat'));
//when client disconnet
socket.on('disconnect', () => {
io.emit('message',formatMessage(appName,'A user has left the chat'))
})
})
//to all the clients in general
//io.emit()
//listen to chat message
socket.on('chatMessage', msg => {
io.emit('message',formatMessage('user',msg))
})
})
server.listen(3000,() => {
winston.info("----Project is up and running----")
});
Since your angular is running on 4200 port and backend running on 3000 port, the origin of both the application is different. For security reasons, it's shown as we are in the development mode of angular.
Basically, by run (Win + r) the following command (or creating a shortcut with it and opening Chrome through that)
chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security
You can open a new "insecure" instance of Chrome at the same time as you keep your other "secure" browser instances open and working as normal.
The error will be resolved in the production mode of the project.
There are two ways you can achieve this
1)By disabling web security in browser using
chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security
2)By adding proxy to angular code.You can find detailed steps here
{
"/api": {
"target": "http://localhost:3000",
"secure": false
}
}
I'm using Angular 10 and the JW Angular Pagination module works fine if I import it into app.module.ts and then use it in a view that uses the app.component.ts component. However, when I try to import it into a custom feature module and use a component that imports the feature module, the pagination element does not display in the view template. It seems that Angular cannot see the pagination module.
App.module.ts
import { NgModule, Component, OnInit } from '#angular/core';
import { CoreModule } from "./core/core.module"
import { MessageModule } from "./messages/message.module";
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import * as $ from 'jquery';
import { BrowserModule } from '#angular/platform-browser';
import { AuthService } from "./model/auth.service"
import { JwPaginationModule } from 'jw-angular-pagination';
#NgModule({
imports: [AppRoutingModule, MessageModule, CoreModule, BrowserModule, JwPaginationModule],
declarations: [AppComponent,],
providers: [AuthService],
bootstrap: [AppComponent]
})
export class AppModule {
}
Core.module.ts
import { NgModule } from "#angular/core";
import { ModelModule } from "../model/model.module";
import { FormsFeatureModule } from "../view/forms.module";
import { ViewFeatureModule } from "../view/view.module";
import { routing } from "../app.routing";
import { MessageModule } from "../messages/message.module";
import { MessageService } from "../messages/message.service";
import { Message } from "../messages/message.model";
import { AuthService } from "../model/auth.service";
import { EncrDecrService } from '../utils/EncrDecr.service';
import { CommonModule } from '#angular/common';
//import { NotFoundComponent } from "./notFound.component";
//import { UnsavedGuard } from './unsaved.guard';
#NgModule({
imports: [ModelModule, MessageModule, routing, FormsFeatureModule, ViewFeatureModule, CommonModule],
declarations: [],
exports: [ModelModule, FormsFeatureModule, ViewFeatureModule, MessageModule ],
providers: [AuthService, EncrDecrService],
})
export class CoreModule {
}
Forms.module.ts
import { NgModule } from "#angular/core";
import { FormsModule, Validators, FormGroup, FormBuilder, NgForm } from '#angular/forms';
import { ReactiveFormsModule } from '#angular/forms';
import { BrowserModule } from '#angular/platform-browser';
import { RouterModule } from '#angular/router';
//import { NotFoundComponent } from "./notFound.component";
//import { UnsavedGuard } from './unsaved.guard';
import { ActivatedRoute, Router } from "#angular/router";
import { AuthService } from "../model/auth.service";
import { JwPaginationModule } from 'jw-angular-pagination';
#NgModule({
imports: [FormsModule, ReactiveFormsModule, BrowserModule, RouterModule, JwPaginationModule],
declarations: [],
exports: [FormsModule, ReactiveFormsModule, RouterModule, JwPaginationModule],
providers: [AuthService],
})
export class FormsFeatureModule {
constructor(private router: Router) { }
View.module.ts
import { RecipeViewComponent } from "../view/recipeView.component";
import { NgModule } from "#angular/core";
import { FormsModule } from '#angular/forms';
import { ReactiveFormsModule } from '#angular/forms';
import { BrowserModule } from '#angular/platform-browser';
import { RouterModule } from '#angular/router';
import { HomePageComponent } from "./homePage.component";
import { AdminComponent } from "../admin/admin.component";
import { AuthService } from "../model/auth.service";
//import { NotFoundComponent } from "./notFound.component";
//import { UnsavedGuard } from './unsaved.guard';
#NgModule({
imports: [FormsModule, ReactiveFormsModule, BrowserModule, RouterModule],
declarations: [RecipeViewComponent, HomePageComponent, AdminComponent],
exports: [RecipeViewComponent, HomePageComponent,AdminComponent, RouterModule],
providers: [AuthService],
})
export class ViewFeatureModule { }
admin.component.ts
import { Component, Inject, DoCheck, ChangeDetectorRef, OnInit } from "#angular/core";
import { ActivatedRoute, Router } from "#angular/router";
import { ModelRepo } from "../model/repository.model";
import { Category } from "../model/category.model";
import { Ingredient } from "../model/ingredient.model";
import { RecipeBook } from "../model/recipeBook.model";
import { User } from "../model/user.model";
import { FormsFeatureModule } from "../view/forms.module"
import { ViewChild, ElementRef } from '#angular/core';
import { EncrDecrService } from '../utils/EncrDecr.service';
import { AppComponent } from '../app.component'
import { Observable, throwError } from "rxjs";
//import { MODES, SharedState, SHARED_STATE } from "./sharedState.model";
//import { Observer} from "rxjs"
#Component(
{
selector: "admin",
templateUrl: "admin.component.html"
}
)
export class AdminComponent implements OnInit {
ModNewCategory = new Category(0,"");
ModNewIngredient = new Ingredient(0,"");
ModNewRecipeBook = new RecipeBook();
selectedConfig = "categories"; //initilze for first page load
selectedCategoryOperation = "addCategory"; //initilze for first page load
selectedIngredientOperation = "addIngredient"; //initilze for first page load
selectedUserOperation = "addUser"; //initilze for first page load
userRoles = new Array<string>("visitor", "member", "administrator");
searchRole = "";
id;
mode;
operation;
defaultObject = new Object();
public pageOfItems: Array<any>;
public items = [];
constructor(public dataRepo: ModelRepo, private EncrDecr: EncrDecrService, private appComponent:AppComponent, activeRoute: ActivatedRoute, public router: Router, public fieldValidator: FormsFeatureModule) {
activeRoute.params.subscribe(params => {
this.id = params["id"];
this.mode = params["mode"];
this.operation = params["operation"]
if (this.operation != null && this.mode != null) {
this.modifyItem(this.id, this.operation);
}
}
)
}
ngOnInit() {
// an example array of 150 items to be paged
// this.items = this.dataRepo.users;
this.items = Array(150).fill(0).map((x, i) => ({ id: (i + 1), name: `Item ${i + 1}` }));
}
onChangePage(pageOfItems: Array<any>) {
// update current page of items
alert('onChangePage got called');
this.pageOfItems = pageOfItems;
}
admin.component.html
<div class="card text-center m-3">
<h3 class="card-header">Angular Pagination Example</h3>
<div class="card-body">
<div *ngFor="let item of pageOfItems">{{item.name}}</div>
</div>
<div class="card-footer pb-0 pt-3">
<jw-pagination [items]="items" (changePage)="onChangePage($event)"></jw-pagination>
</div>
</div>
The Problem
You are using Angular10...
Have a look at the below statement Ivy is not complaining about unknown element inside ng-template
#36171
This is due to an architectural change in Ivy. In the previous compiler (ViewEngine), the check for unknown elements would occur during parsing of the template. In Ivy, templates are parsed independently from the corresponding NgModule, so information on components/directives in scope is not available.
Instead, checking of elements is pushed into the template type checking phase and it's currently affected by the type checker's configuration. With fullTemplateTypeCheck set to true however, it should descend into templates to check them (when it's false, it won't for backwards compatibility reasons). This conflicts however with your statement here:
The issue can only be found in runtime (no component being rendered) or with fullTemplateTypeCheck: true.
Consider the imports array in the module you are declaring AdminComponent
imports: [FormsModule, ReactiveFormsModule, BrowserModule, RouterModule],
This module does not have any idea about a JwPaginationModule
Solution
The simplest solution is to simply add JwPaginationModule to this array
imports: [FormsModule, ReactiveFormsModule, BrowserModule, RouterModule, JwPaginationModule],
Now the module will know about this component and render correctly.
Situation:
I'm using Angular CLI. And I'm trying to receive data from the server side (node.js, express). I created new component card-object. I copied this code from the example on this page: https://angular.io/guide/http
app.module.ts:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { HttpClientModule } from '#angular/common/http';
import { MatGridListModule, MatCardModule } from '#angular/material';
import { AppComponent } from './app.component';
import { CardObjectComponent } from './card-object/card-object.component';
#NgModule({
declarations: [
AppComponent,
CardObjectComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
MatGridListModule,
MatCardModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.html:
<app-card-object></app-card-object>
card-object.component.ts:
import { Component, OnInit, ViewEncapsulation } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'app-card-object',
templateUrl: './card-object.component.html',
styleUrls: ['./card-object.component.css'],
encapsulation: ViewEncapsulation.None
})
export class CardObjectComponent implements OnInit {
results: string[];
constructor(private http: HttpClient) {}
ngOnInit(): void {
this.http.get('http://localhost:3000/?cll=bjc').subscribe(data => {
this.results = data['results'];
});
}
}
card-object.component.html:
<p>{{results[0]}}</p>
<p>some text</p>
node.js:
app.get('/', (req, res) => {
var reqCard = {
results: ['text 1', 'text 2']
};
res.json(reqCard);
});
Problem:
I see that json data I receive successfully (I can see them in google DevTool => Network => XHR). But everything that I see in my angular app is 'some text'. And I see ERROR TypeError: Cannot read property '0' of undefined in my DevTool console.
Question:
Where is a mistake? What have I missed?
Initialize your array so that it has a value before the async call completes:
ngOnInit(): void {
this.results = []
this.http.get('http://localhost:3000/?cll=bjc').subscribe(data => {
this.results = data['results'];
});
}
Bind if results has data:
<p>{{results.length > 0 ? results[0]: ''}}</p>
<p>some text</p>
I don't know but, Some weird thing happening up, I referred the default code provided on "Angular.io" to perform angular service calls, but some how ngOninit method is not getting called.
I have also implemented component from OnInit. and added #Injectable to user.services.ts. But still don't know where I am getting wrong.
Below is the code for the reference.
app.component.ts
//app.components.ts
import { Component } from '#angular/core';
import {User} from './user';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Society CRM';
}
user.ts
export class User
{
_id : string;
name: string;
email: string;
username: string;
password: string;
phone: string;
address: string;
role: string;
created_date: string;
}
user-list.component.ts
import {Component,OnInit} from '#angular/core';
import {User} from './user';
import {UserService} from './user.service';
import { Headers, RequestOptions } from '#angular/http';
#Component({
selector:'user-list',
templateUrl:'./user-list.html',
providers: [ UserService ]
})
export class UserListComponent implements OnInit{
errorMessage: string;
users: User[];
mode = 'Observable';
constructor (private userService: UserService) {};
ngOnInit() {
this.getUsersList();
alert('here');
}
getUsersList() {
return this.userService.getUsersList()
.subscribe(
users => this.users = users,
error => this.errorMessage = <any>error);
}
}
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpModule } from '#angular/http';
import { AppComponent } from './app.component';
import { UserListComponent } from './user-list.component';
import { UserService } from './user.service';
import { FormsModule } from '#angular/forms'; // <-- NgModel lives here
#NgModule({
declarations: [
AppComponent,
UserListComponent
],
imports: [
BrowserModule,
HttpModule,
FormsModule
],
providers: [UserService],
bootstrap: [AppComponent]
})
export class AppModule { }
user.service.ts
import {Injectable} from '#angular/core';
import {Http, Response} from '#angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import {User} from './user';
import { Headers, RequestOptions } from '#angular/http';
#Injectable()
export class UserService
{
constructor (private http:Http){}
private api_url = "http://localhost:3000/api/";
getUsersList() : Observable<User[]>
{
let headers = new Headers();
headers.append('Access-Control-Allow-Origin', '*');
headers.append('Access-Control-Allow-Credentials', 'true');
headers.append('Access-Control-Allow-Methods', 'GET');
headers.append('Access-Control-Allow-Headers', 'Content-Type');
let options = new RequestOptions({headers: headers});
return this.http.get(this.api_url+'getUsersList',options)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || {};
}
private handleError(error: Response | any) {
// In a real world app, you might use a remote logging infrastructure
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}
I don't know what exactly is happening with the above code, no error being shown on firebug console or browser console. Any help would be thankful
Change your app.component.html code by adding this:
<user-list></user-list>
OnInit isn't called because you don't use user-list.component.
Check that you indeed use the component...
For example is the tag <user-list></user-list> defined somewhere in your html?