Angular 4 Firebase error message is not showing on first click - javascript

I am working on Firebase authentication with angular 4. I am trying to display the error messages but it is showing on the second click. In the console, it shows the error on the first click, but when I bind it to HTML component it shows the click on the second click. I am using the following auth service.
import { Injectable } from '#angular/core';
import { AngularFireDatabaseModule, AngularFireDatabase } from 'angularfire2/database';
import { AngularFireAuth } from 'angularfire2/auth';
import { Router } from "#angular/router";
import * as firebase from 'firebase';
#Injectable()
export class AuthService {
authState: any = null;
isLoggedIn: any;
error: any;
constructor(private afAuth: AngularFireAuth,
private db: AngularFireDatabase,
private router:Router) {
this.afAuth.authState.subscribe((auth) => {
this.authState = auth
});
}
// Returns true if user is logged in
get authenticated(): boolean {
return this.authState !== null;
}
// Returns current user data
get currentUser(): any {
return this.authenticated ? this.authState : null;
}
// Returns
get currentUserObservable(): any {
return this.afAuth.authState
}
// Returns current user UID
get currentUserId(): string {
return this.authenticated ? this.authState.uid : '';
}
emailLogin(email:string, password:string) {
return this.afAuth.auth.signInWithEmailAndPassword(email, password)
.then((user) => {
this.router.navigate(['/dashboard_home'])
this.isLoggedIn = this.authenticated;
})
.catch(error => {
this.error = error;
console.log(error)
});
}
// Sends email allowing user to reset password
resetPassword(email: string) {
var auth = firebase.auth();
return auth.sendPasswordResetEmail(email)
.then(() => console.log("email sent"))
.catch((error) => console.log(error))
}
//// Sign Out ////
signOut(): void {
this.afAuth.auth.signOut();
this.router.navigate(['/administrator'])
}
//// Helpers ////
private updateUserData(): void {
// Writes user name and email to realtime db
// useful if your app displays information about users or for admin features
let path = `users/${this.currentUserId}`; // Endpoint on firebase
let data = {
email: this.authState.email,
name: this.authState.displayName
}
this.db.object(path).update(data)
.catch(error => console.log(error));
}
}
My login.html page looks like that.
<div class="card-block">
<div class="alert alert-danger" role="alert" *ngIf="error">{{ error }}</div>
<form autocomplete="off" id="loginAdmin" (submit)="loginAdmin($event)">
<div class="row">
<div class="col-md-4 mx-auto">
<mat-form-field>
<input type="text" id="username" name="username" matInput placeholder="Användarnamn">
</mat-form-field>
</div>
</div>
<div class="row">
<div class="col-md-4 mx-auto">
<mat-form-field>
<input type="password" id="password" name="password" matInput placeholder="Lösenord">
</mat-form-field>
</div>
</div>
<div class="row"></div>
<div class="row">
<div class="col-md-12 text-center">
<button type="submit" mat-raised-button>Logga in</button>
</div>
</div>
</form>
</div>
and my component.ts for login page is given
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../services/auth/auth.service';
import {Router} from "#angular/router";
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
error = '';
constructor(private authService: AuthService, private router: Router) { }
ngOnInit() {
}
loginAdmin(e) {
e.preventDefault();
var email = e.target.elements[0].value;
var password = e.target.elements[1].value;
if(email && password) {
var responses = this.authService.emailLogin(email, password);
this.error = this.authService.error;
}
}
}
If you use the above service you can login use. but it shows errors in the console if email and password are not correct, and it is not showing on binding with HTML.
The binding look like that.
<div class="alert alert-danger" role="alert" *ngIf="error">{{ error }}</div>
Now What I want, to send display error on first click as well as to get all the user data logged in.

I fond the solution. This service work for me.
import {AngularFireAuth} from 'angularfire2/auth';
#Injectable()
export class AuthService {
authState: any = null;
constructor(private afAuth: AngularFireAuth, private router: Router) {
this.afAuth.authState.subscribe((auth) => {
this.authState = auth
});
}
get isUserAnonymousLoggedIn(): boolean {
return (this.authState !== null) ? this.authState.isAnonymous : false
}
get currentUserId(): string {
return (this.authState !== null) ? this.authState.uid : ''
}
get currentUserName(): string {
return this.authState['email']
}
get currentUser(): any {
return (this.authState !== null) ? this.authState : null;
}
get isUserEmailLoggedIn(): boolean {
if ((this.authState !== null) && (!this.isUserAnonymousLoggedIn)) {
return true
} else {
return false
}
}
signUpWithEmail(email: string, password: string) {
return this.afAuth.auth.createUserWithEmailAndPassword(email, password)
.then((user) => {
this.authState = user
})
.catch(error => {
console.log(error)
throw error
});
}
loginWithEmail(email: string, password: string) {
return this.afAuth.auth.signInWithEmailAndPassword(email, password)
.then((user) => {
this.authState = user
})
.catch(error => {
console.log(error)
throw error
});
}
signOut(): void {
this.afAuth.auth.signOut();
this.router.navigate(['/'])
}
}
For more detail visit Angular 4 Firebase Auth – Email/Password Authentication with AngularFire2 v4

Related

Angular async validation not printing error message

Below is my Component :
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
import { HttpService } from './http.service';
import { ProjectidService } from './projectid.service';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
projectDetailForm: FormGroup;
public submitted = false;
constructor(private fb: FormBuilder, private projectidvalidator: ProjectidService) { }
ngOnInit() {
this.projectDetailForm = this.fb.group({
projectid: ['', [Validators.required], [this.projectidvalidator.validate.bind(this.projectidvalidator)]],
projectname: ['name', Validators.required]
})
}
get f() { return this.projectDetailForm.controls; }
get validprojectid() { return this.projectDetailForm.get('projectid'); }
onSubmit(form: FormGroup) {
this.submitted = true;
// stop here if form is invalid
if (this.projectDetailForm.invalid) {
return;
}
console.log('Valid?', this.projectDetailForm.valid); // true or false
console.log('ID', this.projectDetailForm.value.projectid);
console.log('Name', this.projectDetailForm.value.projectname);
}
}
My Service :
import { Injectable } from '#angular/core';
import { Observable, of } from 'rxjs';
import { delay, tap, debounceTime } from 'rxjs/operators';
#Injectable()
export class HttpService {
constructor() { }
checkProjectID(id): Observable<any> {
// Here I will have valid HTTP service call to check the data
return of(true)
}
}
My Async validator :
import { HttpService } from './http.service';
import { Injectable } from '#angular/core';
import { AsyncValidator, AbstractControl, ValidationErrors } from '#angular/forms';
import { Observable, of } from 'rxjs';
import { map, catchError, debounceTime, switchMap } from 'rxjs/operators';
#Injectable()
export class ProjectidService {
constructor(private _httpService:HttpService) { }
validate(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
console.log(control.value);
return control.valueChanges.pipe(
debounceTime(500),
switchMap(_ => this._httpService.checkProjectID(control.value).pipe(
map(isTaken => {
console.log(isTaken);
if (isTaken) {
return { noproject: true }
} else {
return null
}
})
)),
catchError(() => null)
);
}
}
and template :
<form [formGroup]="projectDetailForm" name="projectdetails" (ngSubmit)="onSubmit(projectDetailForm)">
<div class="form-group">
<label for="id">Project ID</label>
<input type="text" class="form-control" id="id" [ngClass]="{ 'is-invalid': f.projectid.invalid && (f.projectid.dirty || f.projectid.touched) }" placeholder="Project ID" name="projectid" formControlName='projectid'>
<button type="button">Validate</button>
<div *ngIf="f.projectid.invalid && (f.projectid.dirty || f.projectid.touched)" class="invalid-feedback">
<div *ngIf="f.projectid.errors.required">Project ID is required</div>
<div *ngIf="f.projectid.errors?.noproject">
Project id is not valid
</div>
</div>
<div *ngIf="f.projectid.errors?.noproject">
Project id is not valid
</div>
{{f.projectid.errors | json}}
</div>
<div class="form-group">
<label for="name">Project Name</label>
<input type="text" class="form-control" id="name" placeholder="Project Name" name="projectname" readonly formControlName='projectname'>
</div>
<div class="form-group d-flex justify-content-end">
<div class="">
<button type="button" class="btn btn-primary">Cancel</button>
<button type="submit" class="btn btn-primary ml-1">Next</button>
</div>
</div>
</form>
Problem is my custom async validation error message is not getting displayed.
Here is stackblitz example
You could do it as follows using rxjs/timer:
import { timer } from "rxjs";
....
return timer(500).pipe(
switchMap(() => {
if (!control.value) {
return of(null);
}
return this._httpService.checkProjectID(control.value).pipe(
map(isTaken => {
console.log(isTaken);
if (isTaken) {
return { noproject: true };
} else {
return null;
}
})
);
})
);
Sample
The real problem is and I have encountered this myself, you subscribe to the value change but you need to wait for the statuschange to return.
It is "PENDING" while it is doing the call.
The debounce/timer/... are just 'hacks' since you never know when the value is returned.
Declare a variable:
this.formValueAndStatusSubscription: Subscription;
In your
this.formValueAndStatusSubscription =
combineLatest([this.form.valueChanges, this.form.statusChanges]).subscribe(
() => this.formStatusBaseOnValueAndStatusChanges = this.form.status
);
Don't forget to desstroy the subscription
The most important point in the async validation is as descriped in Angular Doc
The observable returned must be finite, meaning it must complete at
some point. To convert an infinite observable into a finite one, pipe
the observable through a filtering operator such as first, last, take,
or takeUntil.
so basically you can use for example take(1) , it'll take the first emission then mark the Observable completed
return control.valueChanges.pipe(
debounceTime(500),
take(1),
switchMap(() =>
this._httpService.checkProjectID(control.value).pipe(
map(isTaken =>
isTaken ? { noproject: true } : null
)
))
)
demo

Problem with login and HTTP POST in Angular

I trying to implements a login system in Angular App, but it redirects to the main view and saves an empty object into Local Storage no meters what I typed into the form, a correct or fake account email and password. It's my first real project and first time to making a login system. Uniformly I don't have permission to show real API here.
The Code:
login.component.html
<div class="content">
<div fxLayout="column" fxLayoutAlign="center center">
<mat-card class="example-card">
<mat-card-header>
<mat-card-title>Dobrodošli!</mat-card-title>
</mat-card-header>
<mat-card-content>
<img class="logo" src="../../assets/dnevnimeni.svg" alt="">
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<mat-form-field>
<input matInput type="email" placeholder="E-Mail" formControlName="email">
<mat-error *nfIf="">Unesite odgovarajući E-Mail</mat-error>
</mat-form-field> <br>
<mat-form-field>
<input matInput type="password" placeholder="Password" formControlName="password">
<mat-error *ngIf="">Unesite validan password</mat-error>
</mat-form-field> <br>
<button mat-stroked-button>Login</button>
</form>
</mat-card-content>
</mat-card>
</div>
</div>
login.component.ts
import { Component, OnInit } from '#angular/core';
import { FormBuilder, Validators, FormGroup } from '#angular/forms';
import { Router } from '#angular/router';
import { AuthService } from '../services/auth.service';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
submitted = false;
returnUrl: string;
error: {};
loginError: string;
constructor(
private fb: FormBuilder,
private router: Router,
private authService: AuthService
) { }
ngOnInit() {
this.loginForm = this.fb.group({
email: ['', Validators.required],
password: ['', Validators.required]
});
this.authService.logout();
}
get email() { return this.loginForm.get('email'); }
get password() { return this.loginForm.get('password'); }
onSubmit() {
this.submitted = true;
this.authService.login( this.email.value, this.password.value).subscribe((data) => {
if (this.authService.isLoggedIn) {
const redirect = this.authService.redirectUrl ? this.authService.redirectUrl : '/';
this.router.navigate([redirect]);
} else {
this.loginError = 'email or password is incorrect.';
}
},
error => this.error = error
);
console.log(this.authService.restaurant.email);
}
}
and auth.service.ts
import { Injectable } from '#angular/core';
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '#angular/common/http';
import { throwError, Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { Restaurant } from '../models/Restaurant';
#Injectable({
providedIn: 'root'
})
export class AuthService {
loginUrl = 'xxxxxxxx';
errorData: {};
restaurant: Restaurant;
constructor(private http: HttpClient) { }
redirectUrl: string;
login(email: string, password: string) {
var postData = "email=" + email + "&password=" + password;
return this.http.post<Restaurant>(this.loginUrl, postData)
.pipe(map(restaurant => {
if (restaurant) {
localStorage.setItem('currentRestaurant', JSON.stringify(restaurant));
}
}),
catchError(this.handleError)
);
}
isLoggedIn() {
if (localStorage.getItem('currentRestaurant')) {
return true;
}
return false;
}
getAuthorizationToken() {
const currentRestaurant = JSON.parse(localStorage.getItem('currentRestaurant'));
return currentRestaurant.token;
}
logout() {
localStorage.removeItem('currentRestaurant');
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong.
console.error(`Backend returned code ${error.status}, ` + `body was: ${error.error}`);
}
// return an observable with a user-facing error message
this.errorData = {
errorTitle: 'Oops! Request for document failed',
errorDesc: 'Something bad happened. Please try again later.'
};
return throwError(this.errorData);
}
}
In the map function you don't return any value and try to transform in object the parameters that sends in the post request;
login(email: string, password: string) {
let postData = {email : email ,password :password};
return this.http.post<Restaurant>(this.loginUrl, postData)
.pipe(map(restaurant => {
if (restaurant) {
localStorage.setItem('currentRestaurant', JSON.stringify(restaurant));
return restaurant;
}
}),
catchError(this.handleError)
);
}
Your post data should be like var postData = {email : email ,password :password} , but you have described get request with query parameters.
Also saving data in observable data stream is bad practice. Each new subscriber triggers execution of this code again
if (restaurant) {
localStorage.setItem('currentRestaurant', JSON.stringify(restaurant));
}
postData should be the object instead of string. also check by console.log in isLoggedIn() method, what data localStorage.getItem('currentRestaurant') returns, if it has a value like "{}" or "null" it will return true in if statement.
isLoggedIn() {
if (localStorage.getItem('currentRestaurant')) {
return true;
}
return false; }

Data are not saved in database

I have api end point which save data to the database, post/comments/
when I test it in postman everything works perfect. but in front end data are saved but only id , the data I want to save from form input author and comment.
here is what is saved in database after a user submit the form inputs:
{
"_id": {
"$oid": "5b26c65ffecfe0047846677d"
},
"author": null,
"description": null
}
Here is component.ts :
import { Component, OnInit} from '#angular/core';
import { MoviesService } from '../movies.service';
import { RouterModule, Routes } from '#angular/router';
import {ActivatedRoute} from '#angular/router';
#Component({
selector: 'app-movie',
templateUrl: './movie.component.html',
styleUrls: ['./movie.component.scss']
})
export class MovieComponent implements OnInit {
movie: object;
review: {};
addreview: any;
addreviews: any[];
constructor(private router: ActivatedRoute, private moviesService: MoviesService) {
this.movie = [];
this.review = [];
this.addreview = [];
this.addreviews = [];
}
addReview(addreview: any): void {
if (!addreview) { return; }
this.moviesService.createReview(addreview)
.then(reviews => {
console.log(reviews);
this.addreviews.push(reviews.addreview);
});
}
ngOnInit() {
this.router.params.subscribe((params) => {
// tslint:disable-next-line:prefer-const
let id = params['id'];
this.moviesService.getMovie(id)
.then(movie => {
this.movie = movie;
});
});
this.router.params.subscribe((params) => {
// tslint:disable-next-line:prefer-const
let id = params['id'];
this.moviesService.getReview(id)
.then(review => {
console.log(review);
this.review = review;
});
});
}
}
Here is service.ts
export class MoviesService {
searchStr: string;
queryUrl = '/search/';
theatreUrl = '/theatre/';
moveUrl = '/movies/';
reviewUrl = '/comments/';
private apiUrl = 'http://localhost:8000';
constructor(private http: Http, private _jsonp: Jsonp) { }
createReview(review: string): Promise<any> {
return this.http.post(this.apiUrl + this.reviewUrl, review)
.toPromise()
.then(this.handleData)
.catch(this.handleError);
}
private handleData(res: any) {
const body = res.json();
console.log(body); // for development purposes only
return body.result || body || {};
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); // for development purposes only
return Promise.reject(error.message || error);
}
}
compo.html
<form (ngSubmit)="addReview(addreview)">
<div class="form-group movie-username">
<label for="author">Name:</label>
<input type="text" class="form-control movie-username_text" id="usr" [(ngModel)]="addreview.author" name="author">
</div>
<div class="form-group movie-textarea">
<label for="movie-textarea_label description">Do you like the movie? leave us a comment below</label>
<textarea class="form-control rounded-0"
id="movie-textarea_textarea" #description="ngModel" rows="10"
[(ngModel)]="addreview.description"
name="description"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
Submitted data are not saved to the database what is wrong with my code? any help will be apreciated, thanks

TypeError: Cannot read property 'Id' of undefined on edit view template - Angular 2

Okay so I have been facing the dreadful:
TypeError: Cannot read property 'Id' of undefined
Before we get started:
#angular/cli: 1.4.4
node: 6.10.3
npm: 3.10.10
Just to give more context, I am trying to perform one way data binding to edit a component by taking the Id from its component class and flow in a single direction to display the view template. That's all.
Below is the following that will hopefully try reproduce the problem and in turn figure out a solution.
SQL Table Definition:
CREATE TABLE [ExampleTable]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Col2] [nvarchar](50) NULL,
[Col3] [int] NULL,
[Col4] [int] NULL
)
ExampleTable.ts
export interface ExampleTable {
Id;
Col2;
Col3;
Col4;
}
export class CreateExampleTableModel {
SomeForeignKey?: number;
Col2: string;
Col2: number;
Col2: number;
}
export class EditExampleTable {
}
empty-tables.component.ts
import {
Component
} from '#angular/core';
import {
Router
} from "#angular/router";
import {
EmptyTableServiceService
} from "../../services/empty-table.service";
import {
EmptyTable
} from "../../models/outModels/EmptyTable";
#Component({
selector: 'app-empty-tables',
templateUrl: './empty-tables.component.html',
styleUrls: ['./empty-tables.component.css']
})
export class EmptyTablesComponent {
//Table data
emptyTable: EmptyTable[];
constructor(
private router: Router,
private emptyTableServiceService: EmptyTableServiceService) {
}
edit(emptyTable: EmptyTable) {
this.router.navigate(['emptyTables/edit', emptyTable.Id]);
}
}
EmptyTableService:
import {
Injectable
} from '#angular/core';
import {
Http
} from '#angular/http';
import 'rxjs/add/operator/toPromise';
import {
EmptyTable,
CreateExampleTableModel
} from "../models/outModels/EmptyTable";
#Injectable()
export class EmptyTableService {
constructor(private http: Http, ) {}
getEmptyTable(Id: string): Promise<EmptyTable> {
return this.http.get(`${this.auth.apiUrl}/api/emptyTables/get/${Id}`, { headers: this.auth.header })
.toPromise()
.then(response => response.json() as EmptyTable)
.catch(error => this.logging.handleError(error));
}
update(emptyTable: EmptyTable): Promise < EmptyTable > {
return this.http.post(`${this.auth.apiUrl}/api/emptyTables/update`, JSON.stringify(emptyTable), {
headers: this.auth.header
})
.toPromise()
.then(response => response.json() as EmptyTable)
.catch(error => this.logging.handleError(error));
}
}
EmptyTableEditComponent:
import {
Component,
OnInit
} from '#angular/core';
import {
ActivatedRoute,
ParamMap,
Router
} from '#angular/router';
import {
EmptyTableService
} from "../../../services/empty-table.service";
import {
EmptyTable
} from "../../../models/outModels/EmptyTable";
export class EmptyTableEditComponent implements OnInit {
model: EmptyTable;
constructor(
private route: ActivatedRoute,
private router: Router,
private emptyTableService: EmptyTableService
) {}
ngOnInit() {
this.loading = true;
this.route.paramMap
.switchMap((params: ParamMap) => this.emptyTableService.getEmptyTable(params.get('Id')))
.subscribe(emptyTable => {
this.model = emptyTable;
});
}
goBack(): void {
this.router.navigate(['/emptyTables']);
}
save(): void {
this.loading = true;
this.emptyTableService.update(this.model).then(
emptyTable => {
this.model = emptyTable;
},
error => {
console.log(error);
}
);
}
}
My suspicion is that in my getEmptyTable(Id: string) which returns a Promise of EmptyTables is that I am passing in my Id parameter as a string value whereas in my table definition from my DB it is an integer however according to my understanding, url parameters are always in string format. I tried the following:
i. Setting my Id to a number data type and I call the toString() on the Idparameter in the apiUrl like so:
getEmptyTable(Id: number): Promise<EmptyTable> {
return this.http.get(`${this.auth.apiUrl}/api/emptyTables/get/${Id.toString()}`, { headers: this.auth.header })
.toPromise()
.then(response => response.json() as EmptyTable)
.catch(error => this.logging.handleError(error));
}
But this does not make much of a difference. Lastly, please find the view template which I render:
<div class="container">
<p-messages [(value)]="messages"></p-messages>
<p-panel *ngIf="model">
<p-header>
Edit EmptyTable {{model.Name}}
</p-header>
<form name="form" (ngSubmit)="save()">
<div class="form-group">
<label>Col 2</label>
<input type="text" class="form-control" name="col2" [(ngModel)]="model.Col2" required />
</div>
<div class="form-group">
<label>Col 3</label>
<input type="text" class="form-control" name="col3" [(ngModel)]="model.Col3" required />
</div>
<div class="form-group">
<button pButton type="button" class="ui-button-secondary" (click)="goBack()" label="Back" icon="fa-chevron-left"></button>
<button pButton class="ui-button-success pull-right" label="Save" icon="fa-save"></button>
<app-loader *ngIf="loading"></app-loader>
</div>
</form>
</p-panel>
</div>
To wrap this up, it complains in the following function:
edit(emptyTable: EmptyTable) {
this.router.navigate(['emptyTables/edit', emptyTable.Id]);
}
Note: Please don't run the snippets as there is no output to them. This was the quickest way to format my code. Manual indentation was not cutting it.
The problem was found below:
<ng-template let-user="rowData" pTemplate="body">
<button type="button" pButton (click)="edit(distributor)" icon="fa-edit"></button>
</ng-template>
let-user should have been changed to let-distributor and all works.

Unexpected end of json input

I am trying to display an alert after a user is registered. I have tried debugging and understood that it is going to error function always ( When a user is registered successfully and a user already exists).
Below is my code. I am not able to understood why is it always going into error.
Any help is appreciated since I am stuck with this from long time. Thanks in advance.
1)Alert Component
import { AlertService } from './../../shared/services/alert.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-alert',
templateUrl: './alert.component.html',
styleUrls: ['./alert.component.css']
})
export class AlertComponent {
private _alertService;
private message: any;
constructor(alertService: AlertService) {
this._alertService = alertService;
}
ngOnInit() {
this._alertService.getMessage().subscribe(message => { this.message = message; });
}
}
2.Alert Template
<div *ngIf="message" [ngClass]="{ 'alert': message, 'alert-success': message.type === 'success',
'alert-danger': message.type === 'error' }">{{message.text}}</div>
3)Register Template
<div class="container">
<h2>Register</h2>
<form name="form" (ngSubmit)="f.form.valid && register()" #f="ngForm" novalidate>
<div class="form-group" [ngClass]="{ 'has-error': f.submitted && !username.valid }">
<label for="username">Username</label>
<input type="text" class="form-control" name="username" [(ngModel)]="model.username" #username="ngModel" required />
<div *ngIf="f.submitted && !username.valid" class="help-block">Username is required</div>
</div>
<div class="form-group" [ngClass]="{ 'has-error': f.submitted && !password.valid }">
<label for="password">Password</label>
<input type="password" class="form-control" name="password" [(ngModel)]="model.password" #password="ngModel" required minlength="10" />
<div *ngIf="f.submitted && !password.valid" class="help-block"> Password is required (minimum 10 characters)</div>
</div>
<div class="form-group">
<button class="btn btn-primary" (click)="registerUser()">Register</button>
<app-alert></app-alert>
<a [routerLink]="['']" class="btn btn-link">Cancel</a>
</div>
</form>
</div>
4)Register Component
import { AlertService } from './../../shared/services/alert.service';
import { RegisterService } from './../../shared/services/register.service';
import { Observable } from 'rxjs/Observable';
import { Component, OnInit } from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
import { AuthService } from '../../shared/services/index';
import { Http, Request, RequestMethod, RequestOptions, Headers, Response } from '#angular/http';
#Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit {
private _authService: AuthService;
private _alertService: AlertService;
private _regsiterService: RegisterService;
private appContent = 'application/json';
private _router: Router;
private baseUrl = 'http://localhost:5000/api/v1/';
model: any = {};
username: string;
password: string;
constructor(authService: AuthService, http: Http, router: Router, registerService: RegisterService, alertService: AlertService) {
this._authService = authService;
this._regsiterService = registerService;
this._router = router;
this._alertService = alertService;
}
ngOnInit() {
}
registerUser() {
this._regsiterService.registerUser(this.model.username, this.model.password)
.subscribe(
data => {
console.log('Calling alert');
this._alertService.success('Registration Successful');
this._router.navigate(['/login']);
},
error => {
console.log('Calling alert');
// this._alertService.error(error);
});
}
}
5)Alert Service
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';
#Injectable()
// Checks if a user is a authenticated user and has the valid token without expiration.
export class AlertService {
private subject = new Subject<any>();
success(message: string) {
console.log('Registration Successful');
this.subject.next({ type: 'success', text: message });
}
// error(message: string) {
// console.log('Registration Failed');
// this.subject.next({ type: 'error', text: message });
// }
getMessage(): Observable<any> { return this.subject.asObservable(); }
}
Below is the Error Screenshot
In your html you have:
(ngSubmit)="f.form.valid && register()"
But your method is:
registerUser() {
// ..
}
So the angular parser cannot find the register method that is defined in your html.
Unexpected end of json input
This error normally happens when you have a http call that gets failed for whatever reason ( wrong url, server is down, port is closed, ) and the returned response from the server is not a JSON.
Have a look at your network tab and see the http cal that you're making, what is that you're getting in the response tab.
Basically this error generally means, Javascript hasn't been able to parse something that it was meant to be JSON
If I were you I would check for typos in the template and ts file.
Also, you can try to just import the services at the top of the file and just add them in the constructor like this :
constructor(private authService: AuthService, private http: Http, private router: Router, private registerService: RegisterService, private alertService: AlertService) { }
I think TS will do the assignment for you.
Then onInit() or any other place you can write this.authService.someMethod() etc.
For sure the "not a function" error indicates misspelling/typo.
As it is mentioned already register() exist in your html template but not in the ts file. I would rename the properties of the RegisterComponent also to make sure that possible typos and bugs would be avoided in the future.
The Unexpected end of json input might be due to the fact that you are not providing a valid json from your server.
I haven't seen the code inside this._regsiterService.registerUser . But I believe there's a response.json() call that causes the issue.

Categories