I want To show the $key of client from firebasedatabase which also called uniquekey maybe like
-Kdl_wRRkn7njxgz4B54
i try but it dont show the key but show the other data in key
also try to replace $key with key dont work . i know it need change in code if any one can thanks :)
client.html
<div class="row">
<div class="col-md-6">
<h2><i class="fa fa-users"></i> Clients</h2>
</div>
<div class="col-md-6">
<h5 class="pull-right text-muted">Total Owed: {{totalOwed | currency:"USD":true}}</h5>
</div>
</div>
<table *ngIf="clients?.length > 0;else noClients" class="table table-striped">
<thead class="thead-inverse">
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Balance</th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let client of clients">
<td>{{client.$key}}</td>
<td>{{client.firstName}} {{client.lastName}}</td>
<td>{{client.email}}</td>
<td>{{client.balance | currency:"USD":true}}</td>
<td><a [routerLink]="['/client/'+client.$key]" href="" class="btn btn-secondary btn-sm"><i class="fa fa-arrow-circle-o-right"></i> Details</a></td>
</tr>
</tbody>
</table>
<ng-template #noClients>
<hr>
<h5>There are no clients in the system</h5>
</ng-template>
client.ts
import { Component, OnInit } from '#angular/core';
import { ClientService } from '../../services/client.service';
import { Client } from '../../models/Client';
#Component({
selector: 'app-clients',
templateUrl: './clients.component.html',
styleUrls: ['./clients.component.css']
})
export class ClientsComponent implements OnInit {
clients:any[];
totalOwed:number;
constructor(
public clientService:ClientService
) { }
ngOnInit() {
this.clientService.getClients().valueChanges().subscribe(clients => {
this.clients = clients;
this.getTotalOwed();
});
}
getTotalOwed(){
let total = 0;
for(let i = 0;i < this.clients.length;i++){
total += parseFloat(this.clients[i].balance);
}
this.totalOwed = total;
console.log(this.totalOwed);
}
}
client.service.ts
import { Injectable } from '#angular/core';
import { AngularFireDatabase} from 'angularfire2/database';
import { AngularFireObject, AngularFireList } from 'angularfire2/database';
import { Observable } from 'rxjs';
import { Client } from '../models/Client';
#Injectable()
export class ClientService {
clients: AngularFireList<any>;
client: AngularFireObject<any>;
constructor(
public af:AngularFireDatabase
) {
this.clients = this.af.list('/clients') as AngularFireList<Client[]>;
}
getClients(){
return this.clients;
}
newClient(client:Client){
this.clients.push(client);
}
getClient(id:string){
this.client = this.af.object('/clients/'+id) as AngularFireObject<Client>;
return this.client;
}
}
Use snapshotChanges().map() to store the key:
constructor(
public af:AngularFireDatabase
) {
this.clientsRef = this.af.list('/clients') as AngularFireList<Client[]>;
this.clients = this.clientsRef.snapshotChanges().pipe(
map(changes =>
changes.map(c => ({ key: c.payload.key, ...c.payload.val() }))
)
);
}
Then you should be able to access it as normal:
<td>{{client.key}}</td>
Related
I'm new to OOP and angular.
currently, I want to use reusable table with pagination that makes a request API if page change (pagination inside table component).
the problem is when I access my method using callback from table component (Child) I got undefined.
but when I try to move pagination to MasterGudang (Parent) Components it's work.
I don't really understand what's going on.
Error undefined
but here some code.
table.component.ts
import { Subject } from 'rxjs';
#Component({
selector: 'ngx-table-custom',
templateUrl: './table.component.html',
styleUrls: ['./table.component.scss']
})
export class TableComponent implements OnInit {
constructor() { }
#Input() items: any;
#Input() callback: any;
#Input() columns: [];
p: number = 1;
#ContentChild('action', { static: false }) actionRef: TemplateRef<any>;
ngOnInit(): void {
this.items = new Subject();
this.items.next();
}
onChangePage = (evt) => {
this.callback()
}
Gudang.component.ts
import { MasterGudangService } from '../../../../#core/services/master-service/menu-gudang/gudang/masterGudang.service';
#Component({
selector: "ngx-gudang",
templateUrl: './gudang.component.html',
styleUrls: ['./gudang.component.scss'],
})
#Injectable({
providedIn: 'root'
})
export class GudangComponent implements OnInit {
constructor(
public masterGudangService: MasterGudangService
) {
console.log(masterGudangService)
}
tableData: [];
isEdit: boolean = false;
currentPage: number = 1;
ngOnInit(): void {
this.getList();
}
getList (page?: number) {
this.masterGudangService.getPgb(page? page: this.currentPage).subscribe(response => {
const { data: { content, totalElements, size, number } } = response;
this.tableData = Object.assign({
data: content,
total: totalElements,
size: size,
number: number
});
});
}
}
And here I passing my function which is getList to table component
gudang.component.html
<ngx-table-custom [callback]="getList" [columns]="column" [items]="tableData">
<ng-template let-item #action>
<div class="row">
<button nbButton status="success" (click)="open(dialog, item, true)" class="mx-2" size="tiny"><nb-icon icon="edit"></nb-icon></button>
<button nbButton status="danger" (click)="onDelete(item)" size="tiny"><nb-icon icon="trash"></nb-icon></button>
</div>
</ng-template>
</ngx-table-custom>
MasterGudangService.ts
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class MasterGudangService {
constructor(private http: HttpClient) { }
getPgb (page: number = 1, perPage: number = 10) :any {
return this.http.get(`my-api-url/pgb?page=${page}&size=${perPage}`)
}
}
table.component.html
<div class="row">
<div class="col-12">
<table class="table table-md table-striped">
<thead>
<tr style="background-color: #3366ff; color: #fff;">
<th *ngFor="let column of columns" class="text-basic">{{ column.value }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of items.data | paginate: { itemsPerPage: 10, currentPage: p, totalItems: items.total }; index as idx;">
<td *ngFor="let column of columns">
<div *ngIf="column.key === 'number';"><b class="text-basic">{{ idx + 1 }}</b></div>
<div *ngIf="column.key !== 'action' && !isNested(column.key);" class="text-basic">{{ item[column.key] }}</div>
<div *ngIf="isNested(column.key);" class="text-basic">{{ getKeys(item, column.key) }}</div>
<!-- <div *ngIf="column.key === 'action; action_container"></div> -->
<ng-template [ngIf]="column.key === 'action'" #action_content>
<ng-container
*ngIf="actionRef"
[ngTemplateOutlet]="actionRef"
[ngTemplateOutletContext]="{$implicit:item}">
</ng-container>
</ng-template>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-12" align="center">
<pagination-controls (pageChange)="onChangePage($event)"></pagination-controls>
</div>
</div>
The context of Gudang.component.ts will not be available using callback from table component.
The proper way to implement should be passing the event instead of passing function for callback
table.component.ts
#Output() pageChange = new EventEmitter()
onChangePage = (evt) => {
this.pageChange.emit(evt);
}
gudang.component.html
<ngx-table-custom (pageChange)="getList($event)" [columns]="column" [items]="tableData">
...
</ngx-table-custom>
based on the error, it seems like masterGudangService is null at the time you are trying to access it. Adding this code might help you eliminate the error and at least debug what is going on and get a step further.
ngOnInit(): void {
if(this.masterGudangService)
this.getList();
else
console.log('service not defined!');
}
You could define a helper Method in GudangComponent
getListCallback() {
return this.getList.bind(this);
}
and use it here
<ngx-table-custom [callback]="getListCallback()" [columns]="column" [items]="tableData">
I created an API using asp.net and I used angular as my front end. I am able to get the data just fine but sometimes I would need to refresh the page once or a few more times in order to actually see the data on my table. I have absolutely no idea why this might be happening. I hope the code I have inserted below will be enough to find the solution to my problem
Here is typescript file of my table component
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import {DataService} from 'src/app/Services/data.service';
import {Anime} from 'src/app/Classes/anime';
import { NgModule } from '#angular/core';
import {MatDialog, MatDialogConfig } from '#angular/material/dialog';
import { DialogComponent } from 'src/app/dialog/dialog.component';
#Component({
selector: 'app-anime-table',
templateUrl: './anime-table.component.html',
styleUrls: ['./anime-table.component.css']
})
export class AnimeTableComponent implements OnInit {
AnimeArray : Anime[] = [] ;
data = false;
constructor(private router : Router,
private dataService : DataService,
private Dialog: MatDialog
) {}
ngOnInit(){
this.dataService.GetAnime()
.subscribe(data => data.forEach(element => {
var anime = new Anime();
anime.AnimeID = element.AnimeID;
anime.AnimeName = element.AnimeName;
anime.Anime_Description = element.Anime_Description;
this.AnimeArray.push(anime);
}))
}// ngOnInit
}//Export
Below is the html stuff
<br />
<button routerLink="/Dashboard" class="btn btn-primary">Go Home</button>
<button
routerLink="/CreateAnime"
class="btn btn-success"
style="margin-left: 15px;"
>
Add new Anime
</button>
<br />
<br />
<table class="table table-striped">
<thead>
<tr>
<th>Anime ID</th>
<th>Anime Name</th>
<th>Anime Description</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let anime of AnimeArray">
<td>{{ anime.AnimeID }}</td>
<td>{{ anime.AnimeName }}</td>
<td>{{ anime.Anime_Description }}</td>
<td>
<!-- <a [routerLink] = "['/Anime']" [queryParams] = "anime.AnimeID" class="btn btn-success"> Edit </a> -->
<button (click)="EditAnime(anime.AnimeID)" class="btn btn-success">
Edit
</button>
<button
(click)="DeleteAnime(anime.AnimeID, anime.AnimeName)"
style="margin-left: 15px;"
class="btn btn-danger"
>
Delete
</button>
</td>
</tr>
</tbody>
</table>
Here is a piece of the dataservice that gets the Anime information from the API i created.
import { Injectable } from '#angular/core';
import {HttpClient} from '#angular/common/http'
import {HttpHeaders} from '#angular/common/http';
import { from, Observable } from 'rxjs';
import {Anime} from '../Classes/anime';
#Injectable({
providedIn: 'root'
})
export class DataService {
url : string;
header : any;
option : any;
constructor(private http : HttpClient) {
this.url = 'http://localhost:50484/api/Values/';
const headerSettings: {[name: string]: string | string[]; } = {};
//this.header = new HttpHeaders(headerSettings);
this.header = {'Authorization' : 'bearer ' + localStorage.getItem('UserToken')}
let headers = new HttpHeaders({'Authorization' : 'bearer ' + localStorage.getItem('UserToken')})
this.option = {headers : headers};
}
GetAnime() : Observable<Anime[]> {
console.log(this.header);
const headers = {'Authorization' : 'bearer ' + localStorage.getItem('UserToken')}
return this.http.get<Anime[]>(this.url + 'GetAllAnime/' , {headers});
}
} // data service
P.S I am currently not seeing any errors in the browser console, the cmd or in visual studio code
Try map data first and replace the entire array, instead of pushing in the array.
ngOnInit() {
this.dataService.GetAnime().subscribe(data => data =>
(this.AnimeArray = data.map(element => {
var anime = new Anime();
anime.AnimeID = element.AnimeID;
anime.AnimeName = element.AnimeName;
anime.Anime_Description = element.Anime_Description;
return anime;
}))
);
} // ngOnInit
This question already has answers here:
JQuery - $ is not defined
(36 answers)
Closed 4 years ago.
I'm trying to add Paging and sorting to my table but I got this error , howerver I follow all the steps which listed here
http://l-lin.github.io/angular-datatables/#/getting-started.
I already check the previous problem but I did't work with me
I install all its dependencies
Here's the code of the component :-
import { Component, OnInit, OnDestroy } from '#angular/core';
import { ProductService } from '../../service/product-service.service';
import { Subscription, Subject } from 'rxjs';
#Component({
selector: 'app-admin-products',
templateUrl: './admin-products.component.html',
styleUrls: ['./admin-products.component.css']
})
export class AdminProductsComponent implements OnInit, OnDestroy {
products: any[];
filteredProducts: any[];
subscribtion: Subscription;
dtOptions: DataTables.Settings = {};
dtTrigger: Subject<any> = new Subject();
constructor(private productService: ProductService) {
this.subscribtion = productService.getAll().
// We take a copy of Products and Assigned to filteredProducts
subscribe(
products => {
this.filteredProducts = this.products = products;
this.dtTrigger.next();
}
);
}
ngOnInit() {
this.dtOptions = {
pagingType: 'full_numbers',
pageLength: 5,
processing: true
};
}
filter(queryStr: string) {
// console.log(this.filteredProducts);
if (queryStr) {
this.filteredProducts = this.products.
filter(p => p.payload.val().title.toLowerCase().includes(queryStr.toLowerCase()));
} else {
this.filteredProducts = this.products;
}
}
ngOnDestroy(): void {
// to UnSubscribe
this.subscribtion.unsubscribe();
}
}
Here's the code of the the HTML :-
I follow also all the steps here
<p>
<a routerLink="/admin/products/new" class="btn btn-primary">New Product</a>
</p>
<p>
<input type="text"
#query
(keyup)="filter(query.value)"
placeholder="Search ..." class="form-control">
</p>
<table
datatable [dtOptions]="dtOptions"
[dtTrigger]="dtTrigger" class="table" >
<thead class="thead-dark">
<tr>
<th scope="col">Title</th>
<th scope="col">Price</th>
<th scope="col">Edit</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let product of filteredProducts">
<td>{{ product.payload.val().title }}</td>
<td>{{ product.payload.val().price }}</td>
<td>
<a [routerLink]="['/admin/products/', product.key]">Edit</a>
</td>
</tr>
</tbody>
</table>
$ not defined mostly means you are not including JQuery.
try adding: to your program
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" type="text/javascript"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js" type="text/javascript"></script>
source
I'm working on loading data from JSON file in Angular 2.
This is my JSON file:
[
{
"processName": "SOUAD_1",
"processStatus": "Hibernating",
"UnprocessedCMSG": 123,
"TempackedCMSG": 10,
"DeferredCMSG": 32.99
},
{
"processName": "SOUAD_2",
"processStatus": "Hibernating",
"UnprocessedCMSG": 123,
"TempackedCMSG": 10,
"DeferredCMSG": 32.99
},
{
"processName": "SOUAD_3",
"processStatus": "Hibernating",
"UnprocessedCMSG": 123,
"TempackedCMSG": 10,
"DeferredCMSG": 32.99
}
]
This is my ts file where I specified the JSON path...
import {
Injectable
} from '#angular/core';
import {
Http,
Headers,
RequestOptions,
Response
} from '#angular/http';
import {
Observable,
Subject
} from 'rxjs/Rx';
import 'rxjs/Rx'; //get everything from Rx
import 'rxjs/add/operator/toPromise';
import {
IProduct
} from "../models/iproduct";
#Injectable()
export class ProcessJsonService {
private jsonFileURL: string = "../Data/jsonfile.json";
constructor(private http: Http) {}
//
getProcesslist(): Observable < IProduct[] > {
return this.http.get(this.jsonFileURL)
.map((response: Response) => <IProduct[]>response.json())
.catch(this.handleError);
}
private handleError(errorResponse: Response) {
console.log(errorResponse.statusText);
return Observable.throw(errorResponse.json().error || "Server error");
}
}
this is my my process-list-component.ts
import { Component, OnInit } from '#angular/core';
import { IProduct } from "../models/iproduct";
import {
Http
} from '#angular/http';
import {
ProcessJsonService
} from '../models/myjsonprocess';
import {
Observable
} from 'rxjs/Rx';
#Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {
pageTitle: string = 'Product List';
imageWidth: number = 50;
imageMargin: number = 2;
showImage: boolean = false;
listFilter: string = '';
processList: IProduct[];
errorMessage: string;
constructor(private _processJsonService: ProcessJsonService) {
this.processList = [];
}
ngOnInit(): void {
let self = this;
self._processJsonService.getProcesslist().subscribe(response => this.processList = response, error => this.errorMessage = < any > error);
}
}
this is my process-list-component
<div class='panel panel-primary'>
<div class='panel-heading'>
{{pageTitle}}
</div>
<div class='panel-body'>
<div class='row'>
<div class='col-md-2'>Filter by:</div>
<div class='col-md-4'>
<input type='text' [(ngModel)]='listFilter' />
</div>
</div>
<div class='row'>
<div class='col-md-6'>
<h3>Filtered by: {{listFilter}} </h3>
</div>
</div>
<div class='table-responsive'>
<table class='table'
*ngIf='processList && processList.length'>
<thead>
<tr>
<th>Process Name</th>
<th>Process Status</th>
<th>Unprocessed CMSG</th>
<th>Tempacked CMSG</th>
<th>Deferred CMSG</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let process of processList">
<td>{{ process.processName }}</td>
<td>{{ process.processStatus | lowercase }}</td>
<td>{{ process.UnprocessedCMSG }}</td>
<td>{{ process.TempackedCMSG}}</td>
<td>{{ process.DeferredCMSG}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
I should get a table where the details of each process are shown. But, in the browser, I'm getting empty page, no data are shown.
Please, any help ??
This is what I'm getting in the console:
AppComponent.html:7 ERROR Error: StaticInjectorError(AppModule)[ProductListComponent -> ProcessJsonService]:
StaticInjectorError(Platform: core)[ProductListComponent -> ProcessJsonService]:
NullInjectorError: No provider for ProcessJsonService!
at _NullInjector.get (core.js:994)
Look at this code:
.subscribe(response => this.processList = response
And then in your template:
*ngFor="let process of processList | async"
You only use async pipe to retrieve values from an Observable/Promise. processList is neither of them, you already subscribed to the data and stored it in the variable, so just remove the async pipe from the template.
I have a simple component in my angular2 app:
#Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css'],
providers: [ProductService, CardService]
})
export class ProductComponent implements OnInit {
private products;
constructor(private productService: ProductService, private cartService: CartService) {
}
ngOnInit() {
this.loadProducts();
}
loadProducts() {
this.productService.getProducts().subscribe(data => this.products = data);
}
addProductToCart(product: Product) {
this.cartService.addProduct(product);
}
basketAmount() {
this.cartService.getNumberOfProducts();
}
html file connected to it:
<div class="basket">
On your card: {{basketAmount()}}
</div>
<table class="table table-striped">
<thead class="thead-inverse">
<tr>
<th>#</th>
<th>Name</th>
<th>Desc</th>
<th>Price</th>
<th>Amount</th>
</tr>
</thead>
<tbody *ngFor="let product of products">
<tr>
<th scope="row">{{product.id}}</th>
<td>{{product.name}}</td>
<td>{{product.description}}</td>
<td>{{product.price}}</td>
<td>{{product.amount}}</td>
<button type="button" class="btn btn-success" (click)="addProductToCart(product)">Add to cart</button>
</tr>
</tbody>
</table>
and CartService
#Injectable()
export class CardService {
private cart: Product[] = [];
constructor() {
}
addProduct(product: Product) {
this.cart.push(product);
}
getTotalPrice() {
const totalPrice = this.cart.reduce((sum, cardItem) => {
return sum += cardItem.price, sum;
}, 0);
return totalPrice;
}
getNumberOfProducts() {
const totalAmount = this.card.reduce((sum, cardItem) => {
return sum += cardItem.amount, sum;
}, 0);
return totalAmount;
}
}
export interface Product {
id: number;
name: string;
description: string;
price: number;
amount: number;
}
I would like to update the number of items on my cart after added something into cart and show it on the view. I add items to cart by click and call addProductToCart method. At the same time I want to update a number of this items by basketAmount() which is defined in CartService and return number of items on the cart. I think I should trigger this basketAmount() method in a some way but I do not know how.
How to do it in a good way?
You have multiple options
After pushing item in your cart just call the basketAmount method again and you should have new value.
You can use BehaviorSubject. In this case you just need to subscribe to it and each time you will push the item to cart it will automatically update your cart.
Ok, I found a solution.
I add a simple numberOfItems variable into ProductComponent:
export class ProductComponent implements OnInit {
private products;
private numberOfItems;
constructor(private productService: ProductService, private cardService: CardService) {
}
ngOnInit() {
this.loadProducts();
}
loadProducts() {
this.productService.getProducts().subscribe(data => this.products = data);
}
addProductToCard(product: Product) {
this.cardService.addProduct(product);
}
basketAmount() {
this.numberOfItems = this.cardService.getNumberOfProducts();
}
}
and on the view I call two methods after click and update numberOfItems:
<div class="basket">
On your card: {{numberOfItems}}
</div>
<table class="table table-striped">
<thead class="thead-inverse">
<tr>
<th>#</th>
<th>Name</th>
<th>Desc</th>
<th>Price</th>
<th>Amount</th>
</tr>
</thead>
<tbody *ngFor="let product of products">
<tr>
<th scope="row">{{product.id}}</th>
<td>{{product.name}}</td>
<td>{{product.description}}</td>
<td>{{product.price}}</td>
<td>{{product.amount}}</td>
<button type="button" class="btn btn-success" (click)="addProductToCard(product); basketAmount()">Add to card</button>
</tr>
</tbody>
</table>