I created a class named alert, and I use it to display alerts whenever new post is created or deleted or changed.
but there is one issue, when I put the setAlert inside a DELETE/POST/PUT function, if the latter is located inside a service component, it gives me an error saying: ERROR
but when I move the function into its component.ts file, it works properly without any issues. So why is that happening and what can I do to make it work in a service?
Here is my Alert.ts:
export class alert{
"status" : boolean;
"text": string;
constructor(){
this.status=false;
this.text="";
}
public setAlert(text){
this.status = true;
this.text = text;
}
public close(){
this.status = false;
}
}
Here is my html file:
<div class="forms container">
<form #postForm="ngForm">
<div class="form-group">
<label for="title">Title</label>
<input [(ngModel)]="formService.form.title"
name="title"
id="title"
type="text"
class="form-control"
>
</div>
<div class="form-group">
<label for="body">Body</label>
<textarea [(ngModel)]="formService.form.body"
name= "body"
id="body"
cols="30"
rows="10"
class="form-control"
></textarea>
</div>
<button class="btn btn-success" (click) = "formService.editForm()">Save</button>
<button class="btn btn-danger pull-right" (click) = "formService.deleteForm()">Delete</button>
<div class="container mt-4">
<div class="row">
<div class="col">
<div *ngIf = "alert.status" class="alert alert-success
alert-dismissible fade show" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"
(click) = "alert.close()">
<span aria-hidden="true">×</span>
</button>
{{alert.text}}
</div>
</div>
</div>
</div>
</form>
</div>
Here is component.ts file:
import { Component, OnInit, OnDestroy } from '#angular/core';
import { ActivatedRoute, Router } from '#angular/router';
import { FormService } from './forms.service';
import { HttpClient } from '#angular/common/http';
import { alert } from './alert';
#Component({
selector: 'app-forms',
templateUrl: './forms.component.html',
styleUrls: ['./forms.component.css']
})
export class FormsComponent implements OnInit {
alert: alert;
id: any;
posts: any;
constructor(public formService: FormService ,private route: ActivatedRoute,
private router: Router, private http: HttpClient) { }
ngOnInit() {
this.id=this.route.snapshot.params['id'];
this.alert = new alert();
this.posts = this.formService.getForms(this.id).subscribe(
(forms: any) => {
this.formService.form = forms[0];
}
);
}
}
And here is service.ts file:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { form } from './form-interface';
import { alert } from './alert';
#Injectable({
providedIn: 'root'
})
export class FormService {
formsUrl = "https://jsonplaceholder.typicode.com/posts";
form: form = {
id: 0,
userId: 0,
title: '',
body: ''
};
alert: alert;
constructor(private http: HttpClient) { }
ngOnInit() {
this.alert = new alert();
}
getForms(id) {
return this.http.get('https://jsonplaceholder.typicode.com/posts'
+ "?id=" + id)
}
editForm() {
fetch(this.formsUrl + "/" + this.form.id, {
method: 'PUT',
body: JSON.stringify(this.form),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
})
.then(response => response.json())
this.alert.setAlert("Post has been successfully saved !");
}
deleteForm() {
this.http.delete(this.formsUrl + "/" + this.form.id)
.subscribe(
data => {
console.log("DELETE Request is successful ", data);
this.alert.setAlert("Post has been successfully deleted !");
},
error => {
console.log("Error", error);
}
);
}
}
Services don't have ngOnInit life cycle, change your code from ngOnInit to constructor.
constructor(private http: HttpClient) {
this.alert = new alert();
}
Only components and directives have life cycle hooks:
A Component has a lifecycle managed by Angular itself. Angular creates it, >renders it, creates and renders its children, checks it when its data-bound >properties change and destroy it before removing it from the DOM.
Directive and component instances have a lifecycle as Angular creates, updates, >and destroys them.
Related
I am implementing a simple Fruit Shop web application using Angular in which I am experiencing a strange exception on which I have spent lots of time, but have NOT found any solution yet.
The overall application's scenario is as follows:
In the root route (page) I am loading a bunch of fruits (each fruit is shown like Bootstrap Card), among which the end-user can choose and add them to his/her Cart (through Add to Card, - and + buttons); and then he/she can go to his/her Cart to checkout and payment process.
My important implemented components are as follows:
products (which is loaded as main component in app component and plays the main page role of the application)
productCard (which plays the Bootstrap Card role and is loaded in products component using an *ngFor
productQuantity (which provides the Add to Card, - and + buttons inside the productCard component. I have implemented this feature as a component, as I want to use this feature in the Cart page, allowing the end-use to add or subtract his/her choices there, too)
I have also implemented some simple models to play the entity roles as follows:
cart.ts (The most important properties and methods of this class are CartItem[] array to persist the items chosen by the end-user inside his/her cart, and also getQuantity(product: Product) method that gets a product and returns a number which refers to the total number of that product inside the end-user's cart at the time)
cart-item.ts (The most important properties of this class are Quantity and Product properties)
product.ts (The most important properties of this class are Name and Fee properties.
Here are the codes be more clear for you:
Products Component Class:
import { Component, OnInit, OnDestroy } from '#angular/core';
import { ProductService } from '../product.service';
import { Product } from '../models/product';
import { Subscription } from 'rxjs';
import { AuthService } from '../auth.service';
import { Cart } from '../models/cart';
import { ShoppingCartService } from '../shopping-cart.service';
#Component({
selector: 'app-products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.css']
})
export class ProductsComponent implements OnInit {
products: Product[];
filteredProducts: Product[];
productsSubscription: Subscription;
cartSubscription: Subscription;
cart: Cart;
constructor(
private productService: ProductService,
public auth: AuthService,
private cartService: ShoppingCartService) {
}
filter(query: string) {
this.filteredProducts = (query) ?
this.products.filter(p => p.Name.toLowerCase().includes(query.toLowerCase())) :
this.products;
}
async ngOnInit() {
if (this.auth.isLoggedIn()) {
(await this.cartService.getCart())
.subscribe(cart => {
this.cart = cart;
this.productService.getAll().then(v =>
v.subscribe(products => {
this.filteredProducts = this.products = products
}));
});
}
}
}
Products Component Markup:
<h4>Welcome to Fruit Shop. <ng-container *ngIf="!auth.isLoggedIn()"> To purchase fruits you must <span>log in first</span>.</ng-container></h4>
<p>
<input type="text" #query (keyup)="filter(query.value)"
placeholder="Type here to search among products..." class="form-control">
</p>
<div class="row">
<ng-container *ngFor="let p of filteredProducts">
<div class="col">
<product-card [product]="p" [cart]="cart"></product-card>
</div>
</ng-container>
</div>
ProductCard Component Class:
import { Component, OnInit, Input } from '#angular/core';
import { Product } from '../models/product';
import { ShoppingCartService } from '../shopping-cart.service';
import { AuthService } from '../auth.service';
import { Cart } from '../models/cart';
#Component({
selector: 'product-card',
templateUrl: './product-card.component.html',
styleUrls: ['./product-card.component.css']
})
export class ProductCardComponent {
#Input('product') product: Product;
#Input('cart') cart: Cart;
constructor(public cartService: ShoppingCartService, public auth: AuthService) {
}
async addToCart() {
this.cartService.addToCart(this.product).subscribe(
res => this.cartService.getCart().then(
res => {
res.subscribe(c => this.cart = c)
}).then(value => this.cartService.totalCartItems += 1)
);
}
}
ProductCard Component Markup:
<div class="card" style="width: 15rem;">
<img class="card-img-top" [src]="product.imageUrl" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">{{ product.Name }}</h5>
<span class="card-text">{{ product.Fee | currency }}</span>
<button
*ngIf="cart && cart.getQuantity(product) > 0"
(click)="cartService.deleteFromCart(product)"
type="button" class="btn btn-danger btn-sm">Delete</button>
</div>
<div class="card-footer">
<button *ngIf="!auth.isLoggedIn() || (cart && cart.getQuantity(product)) === 0; else updateQuantity"
[ngClass]="!auth.isLoggedIn() ? 'button-not-allowd' : 'button-cursor'"
[disabled]="!auth.isLoggedIn()"
(click)="addToCart() " class="btn btn-primary btn-block ">Add to Cart</button>
<ng-template #updateQuantity>
<product-quantity [product]="product" [cart]="cart"></product-quantity>
</ng-template>
</div>
</div>
ProductQuantity Component Class:
import { Component, OnInit, Input } from '#angular/core';
import { Product } from '../models/product';
import { Cart } from '../models/cart';
import { ShoppingCartService } from '../shopping-cart.service';
#Component({
selector: 'product-quantity',
templateUrl: './product-quantity.component.html',
styleUrls: ['./product-quantity.component.css']
})
export class ProductQuantityComponent {
#Input('product') product: Product;
#Input('cart') cart: Cart;
constructor(private cartService: ShoppingCartService) {
}
async addToCart() {
this.cartService.addToCart(this.product).subscribe(
res => this.cartService.getCart().then(
res => {
res.subscribe(c => this.cart = c)
}).then(value => this.cartService.totalCartItems += 1)
);
}
subtractFromCart() {
this.cartService.subtractFromCart(this.product).subscribe(
res => this.cartService.getCart().then(
res => res.subscribe(c => this.cart = c)).then(value => this.cartService.totalCartItems -= 1)
);
}
deleteFromCart() {
this.cartService.deleteFromCart(this.product).subscribe(
res => this.cartService.getCart().then(
res => res.subscribe(c => this.cart = c))
.then(value => this.cartService.totalCartItems -= 1)
);
}
}
ProdcutQuantity Component Markup:
<div class="row no-gutters">
<div class="col-2 ">
<button (click)="cart.getQuantity(product) > 1 ? subtractFromCart() : deleteFromCart()"
class="btn btn-secondary btn-block ">-</button>
</div>
<div class="col text-center quantity-text">
{{ cart.getQuantity(product) }} in cart
</div>
<div class="col-2 ">
<button (click)="addToCart()" class="btn btn-secondary btn-block ">+</button>
</div>
</div>
Cart Service which is a service and is used to communicate to the server side of the application about cart related things:
import { Injectable } from '#angular/core';
import { Product } from './models/product';
import { AuthService } from './auth.service';
import { Router } from '#angular/router';
import { Cart } from './models/cart';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Observable, of } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class ShoppingCartService {
totalCartItems: number = 0;
constructor(private auth: AuthService, private router: Router, private http: HttpClient) {
if (auth.isLoggedIn()) {
this.getCart().then(resp =>
resp.subscribe(cart => cart.CartItems.forEach(item => this.totalCartItems += item.Quantity)))
}
}
addToCart(product: Product) {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem('token')
})
};
return this.http.post(
`http://localhost/FruitShop/api/v1/CartItems/AddItemByItemId/?productId=${product.Id}`,
{},
httpOptions);
}
subtractFromCart(product: Product) {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem('token')
})
};
return this.http.post(
`http://localhost/FruitShop/api/v1/CartItems/SubstractItemByItemId/?productId=${product.Id}`,
{},
httpOptions);
}
deleteFromCart(product: Product) {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem('token')
})
};
return this.http.post(
`http://localhost/FruitShop/api/v1/CartItems/DeleteItemByItemId/?productId=${product.Id}`,
{},
httpOptions);
}
async getCart(): Promise<Observable<Cart>> {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem('token')
})
};
return this.http.get<Cart>('http://localhost/FruitShop/api/v1/Cart/GetCart', httpOptions);
}
}
cart.ts which is my cart model:
import { CartItem } from './cart-item';
import { Product } from './product';
export class Cart {
Id: number;
IsActive: Boolean;
IsDeleted: Boolean;
CreatedAt: Date;
User_Id: number;
Coupons_Id: number;
CartItems: CartItem[];
getQuantity(product: Product): number {
let count: number = 0;
this.CartItems
.filter(ci => ci.Products_Id == product.Id)
.forEach(i => {
count += i.Quantity;
});
return count;
}
}
cart-item.ts which is my CartItem model:
import { Product } from './product';
export class CartItem {
constructor(
public Id: number,
public Quantity: number,
public ModifiedAt: Date,
public IsDeleted: Boolean,
public Products_Id: number,
public Carts_Id: number,
public Products: Product
)
{}
get totalPrice() {
return this.Quantity * this.Products.Fee;
}
}
product.ts which is my Product model:
export class Product {
constructor(public Id: number, public Name: string, public Fee: number, public imageUrl: string){
}
}
Here is the exception that I don't know how to solve it, after searching the web and google a lot:
core.js:6185 ERROR TypeError: ctx.cart.getQuantity is not a function
at ProductCardComponent_Template (product-card.component.html:7)
at executeTemplate (core.js:11949)
at refreshView (core.js:11796)
at refreshComponent (core.js:13229)
at refreshChildComponents (core.js:11527)
at refreshView (core.js:11848)
at refreshDynamicEmbeddedViews (core.js:13154)
at refreshView (core.js:11819)
at refreshComponent (core.js:13229)
at refreshChildComponents (core.js:11527)
I guess the problem is that cart isn't instantly available and comes from a subscription in Products Component Class. It means at the beginning in a moment of time it is undefined and getQuantity isn't a function.
Try the next thing to solve it: add ngIf on the div.row
Products Component Markup:
<h4>Welcome to Fruit Shop. <ng-container *ngIf="!auth.isLoggedIn()"> To purchase fruits you must <span>log in first</span>.</ng-container></h4>
<p>
<input type="text" #query (keyup)="filter(query.value)"
placeholder="Type here to search among products..." class="form-control">
</p>
<div class="row" *ngIf="cart">
<ng-container *ngFor="let p of filteredProducts">
<div class="col">
<product-card [product]="p" [cart]="cart"></product-card>
</div>
</ng-container>
</div>
now the product cart will be rendered only when the cart exists that shouldn't cause the error.
I am trying to create a form in angular that takes a name, passes it to a URL, and returns a portion of a .json file. I can't figure out why the url is not getting updated though.
The HTML:
<form (ngSubmit)="processForm($engineer)">
<div class="form-group">
<label for="engineerselectform">Engineer Name</label>
<select class="form-control" id="engineerselectform" name="engineer" [(ngModel)]="engineer">
<option></option>
<option>Smith</option>
<option>Jones</option>
<option>Clark</option>
</select>
</div>
<input class="btn btn-primary" type="submit" value="submit" aria-pressed="true">
</form>
The Component:
import { Component, OnInit } from '#angular/core';
import { ScheduleService } from '../schedule.service';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-schedule',
templateUrl: './schedule.component.html',
styleUrls: ['./schedule.component.scss']
})
export class ScheduleComponent implements OnInit {
engineer;
constructor(
private scheduleService: ScheduleService,
private route: ActivatedRoute
) { }
ngOnInit() {}
processForm(engineer: string) {
this.route.params.subscribe(params=> { const engineer = params["engineer"];
this.scheduleService.getschedule(engineer).subscribe(engineer => this.engineer = engineer);
});
}
}
The Service:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class ScheduleService {
apiUrl ='http://127.0.0.1:5000/schedule'
engineer;
constructor(private http: HttpClient) { }
getschedule(engineer: string){
return this.http.get(`${this.apiUrl}?engineer=${this.engineer}`);
}
}
The Flask API backend:
#app.route('/schedule', methods = ['GET'])
def engineer_location_api():
if "engineer" in request.args:
print ('did this')
engineer_name = request.args["engineer"]
print ("engineer name:", engineer_name)
else:
return "not found, sorry"
answer = {}
with open(LOC1, "r") as file:
check_loc1 = json.load(file)
for item in check_loc1["LOC1"]:
if engineer_name in item["Engineer"]:
answer.update(item)
else:
continue
with open(LOC2, "r") as file:
check_loc2 = json.load(file)
for item in check_loc2:
if engineer_name in item:
answer.update(item)
else:
continue
if answer:
return answer
else:
return 'engineer not found'
app.run()
the error:
ERROR
Object { headers: {…}, status: 200, statusText: "OK", url: "http://127.0.0.1:5000/schedule?engineer=undefined", ok: false, name: "HttpErrorResponse", message: "Http failure during parsing for http://127.0.0.1:5000/schedule?engineer=undefined", error: {…} }
core.js:6014:19
As I understand it, when I hit submit the process form function should send the engineer variable to the component where it sets it as a parameter that it provides to the service which should fill out the URL. But regardless of how I play around with it, the engineer always comes back as undefined. Clearly I'm missing something core to passing the variable.
Also, I'm super new and therefore there are probably other things in this code that are ugly or not best practice, feel free to rip into it, I figure my understanding can only go up.
You don't have to subscribe to activated url if your data is coming from form. You have to remove the $event from processForm because we will add the global variable in your service function. Please have a look on below example
<form (ngSubmit)="processForm()">
<div class="form-group">
<label for="engineerselectform">Engineer Name</label>
<select class="form-control" id="engineerselectform" name="engineer" [(ngModel)]="engineer">
<option></option>
<option value="smith">Smith</option>
<option value="jones">Jones</option>
<option value="clark">Clark</option>
</select>
</div>
<input class="btn btn-primary" type="submit" value="submit" aria-pressed="true">
</form>
import { Component, OnInit } from '#angular/core';
import { ScheduleService } from '../schedule.service';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-schedule',
templateUrl: './schedule.component.html',
styleUrls: ['./schedule.component.scss']
})
export class ScheduleComponent implements OnInit {
engineer;
receivedEngineers;
constructor(
private scheduleService: ScheduleService,
private route: ActivatedRoute
) { }
ngOnInit() {}
processForm() {
this.scheduleService.getschedule(this.engineer).subscribe(engineer => this.receivedEngineers = engineer);
});
}
}
getschedule(engineer: string){
return this.http.get(`${this.apiUrl}?engineer=${engineer}`);
}
The engineer is now accessed from parameter of getSchedule() function.
I have been trying to hide my form and making it appear only when user click on the button. but for some reason, the function I have created never work is there something wrong with my code? and I saw quite a few example that uses angular.module and I tried it but I always get an error message.
transfer.component.html
<form [formGroup]="AddRiciverForm" id="AddRiciverForm" (ngSubmit)="addRiciverFunc()" *ngIf="show">
<div class="container">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<p><input type="email" id="emailTo" formControlName="emailTo" placeholder="Reciver Email" [(ngModel)]="this.AddRiciverForm.value.emailTo" required></p>
</div>
</div>
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<p><button class="btn btn-primary" type="submit" [disabled]="!transferForm.form.valid">Add</button> </p>
</div>
</div>
</div>
</form>
<button ng-click="AddEmailFunc()">add user</button>
transfer.component.ts
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../auth.service';
import { FormBuilder, FormGroup } from '#angular/forms';
import { Router } from '#angular/router';
import { Http } from '#angular/http';
import { PostsService } from '../posts.service';
#Component({
selector: 'app-transfer',
templateUrl: './transfer.component.html',
styleUrls: ['./transfer.component.css']
})
export class TransferComponent implements OnInit {
constructor(private fb: FormBuilder, private http: Http, private router: Router, private auth: AuthService,private postsService: PostsService) { }
transfer = {};
addRiciver = {};
recivers: any;
AddRiciverForm: FormGroup;
transferForm: FormGroup;
public userEmail: string;
show=false;
ngOnInit() {
this.transferForm = this.fb.group({
emailTo: '',
amount: ''
});
this.AddRiciverForm = this.fb.group({
emailTo: ''
});
this.auth.currentEmail.subscribe(email => this.userEmail = email);
this.postsService.getAllReciver().subscribe(reciver => {
this.recivers = reciver;
});
}
transFunds(){
}
addRiciverFunc(){
this.addRiciver={
emailFrom: this.userEmail,
emailTo: this.AddRiciverForm.value.emailTo
}
this.http.post('/transfer', this.addRiciver)
.subscribe(res => {
let id = res['_id'];
}, (err) => {
console.log(err);
}
);
}
AddEmailFunc(){
if(!this.show){
this.show = true;
}
}
}
You must try adding [hidden]="AddEmailFunc()" on your form.
please see my sample code
import { Component } from '#angular/core';
#Component({
selector: 'Sandbox',
template: `<form [hidden]="isDisplayed">
<label>Sample: </label>
<input type="text">
</form>
<button (click)="showMe()">Click</button>`
})
export class SandboxComponent{
isDisplayed = true;
showMe()
{
if(this.isDisplayed)
{
this.isDisplayed = false;
}else{
this.isDisplayed = true;
}
}
}
Hope it helps. :) cheers!
You are mixing angularjs (1.x) and angular (>2)
the ng-click in Angular should be:
<button (click)="AddEmailFunc()">add user</button>
If this does not solve your issue please post the full component.
you can use *ngIf in and (model) binded to event click of button.
<button (click)="changeView()">add user</button>
and clickEvent
changeView(){
this.showForm = !this.showForm;
}
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.
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.