我有一个使用angular 7的模板,并且文件中有一个false-db。我需要使用Firebase。
模板:https://themeforest.net/item/fuse-angularjs-material-design-admin-template/12931855
我已经安装了Firebase并准备就绪,但是我不知道如何在firebase代码中转换模板上的false-db的代码。
组件代码:
import { Component, ElementRef, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { MatPaginator, MatSort } from '@angular/material';
import { DataSource } from '@angular/cdk/collections';
import { BehaviorSubject, fromEvent, merge, Observable, Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseUtils } from '@fuse/utils';
import { EcommerceProductsService } from 'app/main/apps/e-commerce/products/products.service';
import { takeUntil } from 'rxjs/internal/operators';
@Component({
selector : 'e-commerce-products',
templateUrl : './products.component.html',
styleUrls : ['./products.component.scss'],
animations : fuseAnimations,
encapsulation: ViewEncapsulation.None
})
export class EcommerceProductsComponent implements OnInit
{
dataSource: FilesDataSource | null;
displayedColumns = ['id', 'image', 'name', 'category', 'price', 'quantity', 'active'];
@ViewChild(MatPaginator)
paginator: MatPaginator;
@ViewChild(MatSort)
sort: MatSort;
@ViewChild('filter')
filter: ElementRef;
// Private
private _unsubscribeAll: Subject<any>;
constructor(
private _ecommerceProductsService: EcommerceProductsService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.dataSource = new FilesDataSource(this._ecommerceProductsService, this.paginator, this.sort);
fromEvent(this.filter.nativeElement, 'keyup')
.pipe(
takeUntil(this._unsubscribeAll),
debounceTime(150),
distinctUntilChanged()
)
.subscribe(() => {
if ( !this.dataSource )
{
return;
}
this.dataSource.filter = this.filter.nativeElement.value;
});
}
}
export class FilesDataSource extends DataSource<any>
{
private _filterChange = new BehaviorSubject('');
private _filteredDataChange = new BehaviorSubject('');
/**
* Constructor
*
* @param {EcommerceProductsService} _ecommerceProductsService
* @param {MatPaginator} _matPaginator
* @param {MatSort} _matSort
*/
constructor(
private _ecommerceProductsService: EcommerceProductsService,
private _matPaginator: MatPaginator,
private _matSort: MatSort
)
{
super();
this.filteredData = this._ecommerceProductsService.products;
}
/**
* Connect function called by the table to retrieve one stream containing the data to render.
*
* @returns {Observable<any[]>}
*/
connect(): Observable<any[]>
{
const displayDataChanges = [
this._ecommerceProductsService.onProductsChanged,
this._matPaginator.page,
this._filterChange,
this._matSort.sortChange
];
return merge(...displayDataChanges)
.pipe(
map(() => {
let data = this._ecommerceProductsService.products.slice();
data = this.filterData(data);
this.filteredData = [...data];
data = this.sortData(data);
// Grab the page's slice of data.
const startIndex = this._matPaginator.pageIndex * this._matPaginator.pageSize;
return data.splice(startIndex, this._matPaginator.pageSize);
}
));
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
// Filtered data
get filteredData(): any
{
return this._filteredDataChange.value;
}
set filteredData(value: any)
{
this._filteredDataChange.next(value);
}
// Filter
get filter(): string
{
return this._filterChange.value;
}
set filter(filter: string)
{
this._filterChange.next(filter);
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Filter data
*
* @param data
* @returns {any}
*/
filterData(data): any
{
if ( !this.filter )
{
return data;
}
return FuseUtils.filterArrayByString(data, this.filter);
}
/**
* Sort data
*
* @param data
* @returns {any[]}
*/
sortData(data): any[]
{
if ( !this._matSort.active || this._matSort.direction === '' )
{
return data;
}
return data.sort((a, b) => {
let propertyA: number | string = '';
let propertyB: number | string = '';
switch ( this._matSort.active )
{
case 'id':
[propertyA, propertyB] = [a.id, b.id];
break;
case 'name':
[propertyA, propertyB] = [a.name, b.name];
break;
case 'categories':
[propertyA, propertyB] = [a.categories[0], b.categories[0]];
break;
case 'price':
[propertyA, propertyB] = [a.priceTaxIncl, b.priceTaxIncl];
break;
case 'quantity':
[propertyA, propertyB] = [a.quantity, b.quantity];
break;
case 'active':
[propertyA, propertyB] = [a.active, b.active];
break;
}
const valueA = isNaN(+propertyA) ? propertyA : +propertyA;
const valueB = isNaN(+propertyB) ? propertyB : +propertyB;
return (valueA < valueB ? -1 : 1) * (this._matSort.direction === 'asc' ? 1 : -1);
});
}
/**
* Disconnect
*/
disconnect(): void
{
}
}
服务代码:
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable()
export class EcommerceProductsService implements Resolve<any>
{
products: any[];
onProductsChanged: BehaviorSubject<any>;
/**
* Constructor
*
* @param {HttpClient} _httpClient
*/
constructor(
private _httpClient: HttpClient
)
{
// Set the defaults
this.onProductsChanged = new BehaviorSubject({});
}
/**
* Resolver
*
* @param {ActivatedRouteSnapshot} route
* @param {RouterStateSnapshot} state
* @returns {Observable<any> | Promise<any> | any}
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any
{
return new Promise((resolve, reject) => {
Promise.all([
this.getProducts()
]).then(
() => {
resolve();
},
reject
);
});
}
/**
* Get products
*
* @returns {Promise<any>}
*/
getProducts(): Promise<any>
{
return new Promise((resolve, reject) => {
this._httpClient.get('api/e-commerce-products')
.subscribe((response: any) => {
this.products = response;
this.onProductsChanged.next(this.products);
resolve(response);
}, reject);
});
}
}
HTML组件
<div id="products" class="page-layout carded fullwidth inner-scroll">
<!-- TOP BACKGROUND -->
<div class="top-bg accent"></div>
<!-- / TOP BACKGROUND -->
<!-- CENTER -->
<div class="center">
<!-- HEADER -->
<div class="header accent"
fxLayout="column" fxLayoutAlign="center center"
fxLayout.gt-sm="row" fxLayoutAlign.gt-sm="space-between center">
<!-- APP TITLE -->
<div class="logo mb-24 mb-md-0"
fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="logo-icon s-32 mr-16" [@animate]="{value:'*',params:{delay:'50ms',scale:'0.2'}}">
shopping_basket
</mat-icon>
<span class="logo-text h1" [@animate]="{value:'*',params:{delay:'100ms',x:'-25px'}}">
Products
</span>
</div>
<!-- / APP TITLE -->
<!-- SEARCH -->
<div class="search-wrapper mx-32 mx-md-0">
<div class="search" fxFlex fxLayout="row" fxLayoutAlign="start center">
<mat-icon>search</mat-icon>
<input #filter placeholder="Search for a product">
</div>
</div>
<!-- / SEARCH -->
<!-- ADD BUTTON -->
<button mat-raised-button
[routerLink]="'/apps/e-commerce/products/new'"
class="add-product-button fuse-white mt-24 mt-md-0">
<span>ADD NEW PRODUCT</span>
</button>
<!-- / ADD BUTTON -->
</div>
<!-- / HEADER -->
<!-- CONTENT CARD -->
<div class="content-card">
<mat-table class="products-table"
#table [dataSource]="dataSource"
matSort
[@animateStagger]="{value:'50'}"
fusePerfectScrollbar>
<!-- ID Column -->
<ng-container matColumnDef="id">
<mat-header-cell *matHeaderCellDef mat-sort-header>ID</mat-header-cell>
<mat-cell *matCellDef="let product">
<p class="text-truncate">{{product.id}}</p>
</mat-cell>
</ng-container>
<!-- Image Column -->
<ng-container matColumnDef="image">
<mat-header-cell *matHeaderCellDef></mat-header-cell>
<mat-cell *matCellDef="let product">
<img class="product-image"
*ngIf="product.featuredImageId" [alt]="product.name"
[src]="product.images[product.featuredImageId].url"/>
<img *ngIf="!product.featuredImageId"
[src]="'assets/images/ecommerce/product-image-placeholder.png'">
</mat-cell>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef mat-sort-header>Name</mat-header-cell>
<mat-cell *matCellDef="let product">
<p class="text-truncate">{{product.name}}</p>
</mat-cell>
</ng-container>
<!-- Category Column -->
<ng-container matColumnDef="category">
<mat-header-cell *matHeaderCellDef fxHide mat-sort-header fxShow.gt-md>Category</mat-header-cell>
<mat-cell *matCellDef="let product" fxHide fxShow.gt-md>
<p class="category text-truncate">
{{product.categories[0]}}
</p>
</mat-cell>
</ng-container>
<!-- Price Column -->
<ng-container matColumnDef="price">
<mat-header-cell *matHeaderCellDef mat-sort-header fxHide fxShow.gt-xs>Price</mat-header-cell>
<mat-cell *matCellDef="let product" fxHide fxShow.gt-xs>
<p class="price text-truncate">
{{product.priceTaxIncl | currency:'USD':'symbol'}}
</p>
</mat-cell>
</ng-container>
<!-- Quantity Column -->
<ng-container matColumnDef="quantity">
<mat-header-cell *matHeaderCellDef mat-sort-header fxHide fxShow.gt-sm>Quantity</mat-header-cell>
<mat-cell *matCellDef="let product" fxHide fxShow.gt-sm>
<span class="quantity-indicator text-truncate"
[ngClass]="{'red-500':product.quantity <= 5, 'amber-500':product.quantity > 5 && product.quantity <= 25,'green-600':product.quantity > 25}">
</span>
<span>
{{product.quantity}}
</span>
</mat-cell>
</ng-container>
<!-- Active Column -->
<ng-container matColumnDef="active">
<mat-header-cell *matHeaderCellDef mat-sort-header fxHide fxShow.gt-xs>Active</mat-header-cell>
<mat-cell *matCellDef="let product" fxHide fxShow.gt-xs>
<mat-icon *ngIf="product.active" class="active-icon green-600 s-16">check</mat-icon>
<mat-icon *ngIf="!product.active" class="active-icon red-500 s-16">close</mat-icon>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns; sticky:true"></mat-header-row>
<mat-row *matRowDef="let product; columns: displayedColumns;"
class="product"
matRipple
[routerLink]="'/apps/e-commerce/products/'+product.id+'/'+product.handle">
</mat-row>
</mat-table>
<mat-paginator #paginator
[length]="dataSource.filteredData.length"
[pageIndex]="0"
[pageSize]="10"
[pageSizeOptions]="[5, 10, 25, 100]">
</mat-paginator>
</div>
<!-- / CONTENT CARD -->
</div>
<!-- / CENTER -->
</div>