Implementing a Book Catalog Interface in ABP Framework with Angular
Configure localization resources to suport multi-language book display. Within the .Domain.Shared project, locate the Localization/BookStore/en.json file and populate it with translation keys:
{
"Culture": "en",
"Texts": {
"Menu:Library": "Library",
"Menu:BookManagement": "Book Management",
"Menu:Catalog": "Catalog",
"PublicationDate": "Publication Date",
"AddVolume": "New Volume",
"LiteratureType": "Type",
"Cost": "Price",
"Confirmation": "Confirmation",
"DeleteConfirmation": "Are you sure you want to remove this volume?",
"Enum:LiteratureType:0": "Unclassified",
"Enum:LiteratureType:1": "Adventure",
"Enum:LiteratureType:2": "Biography",
"Enum:LiteratureType:3": "Dystopian",
"Enum:LiteratureType:4": "Fantasy",
"Enum:LiteratureType:5": "Horror",
"Enum:LiteratureType:6": "Science",
"Enum:LiteratureType:7": "Sci-Fi",
"Enum:LiteratureType:8": "Poetry"
}
}
Keys prefixed with Menu: render in navigation structures, while Enum: prefixes map enumeration values to display strings.
Ensure the development environment meets the following requirements:
# Verify Node.js installation
node --version
# Install package manager
npm install -g yarn
# Install Angular CLI globally
npm install -g @angular/cli
Ganerate the presentation layer module using the Angular CLI:
ng generate module library --module app --routing --route catalog
This creates the necessary scaffolding. Update src/app/library/library.module.ts to import shared ABP components:
import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { LibraryRoutingModule } from './library-routing.module';
import { CatalogComponent } from './catalog.component';
@NgModule({
declarations: [CatalogComponent],
imports: [
LibraryRoutingModule,
SharedModule
]
})
export class LibraryModule { }
Configure lazy loading in app-routing.module.ts:
{
path: 'catalog',
loadChildren: () => import('./library/library.module').then(m => m.LibraryModule)
}
Register navigation items in route.provider.ts:
function configureNavigation(routes: RoutesService) {
return () => {
routes.add([
{
path: '/',
name: '::Menu:Library',
iconClass: 'fas fa-home',
order: 1,
layout: eLayoutType.application,
},
{
path: '/book-management',
name: '::Menu:BookManagement',
iconClass: 'fas fa-book-reader',
order: 2,
layout: eLayoutType.application,
},
{
path: '/catalog',
name: '::Menu:Catalog',
parentName: '::Menu:BookManagement',
layout: eLayoutType.application,
},
]);
};
}
Implement the presentation logic in catalog.component.ts:
import { ListService, PagedResultDto } from '@abp/ng.core';
import { Component, OnInit } from '@angular/core';
import { VolumeDto } from './models';
import { VolumeService } from './services';
@Component({
selector: 'app-catalog',
templateUrl: './catalog.component.html',
styleUrls: ['./catalog.component.scss'],
providers: [ListService],
})
export class CatalogComponent implements OnInit {
inventory = { items: [], totalCount: 0 } as PagedResultDto<VolumeDto>;
constructor(
public readonly list: ListService,
private volumeService: VolumeService
) {}
ngOnInit(): void {
const dataSource = (queryParams) => this.volumeService.getPagedList(queryParams);
this.list.hookToQuery(dataSource).subscribe((result) => {
this.inventory = result;
});
}
}
Create the view template in catalog.component.html:
<div class="card">
<div class="card-header">
<div class="row">
<div class="col-md-6">
<h5 class="card-title">
{{ '::Menu:Catalog' | abpLocalization }}
</h5>
</div>
<div class="col-md-6 text-right"></div>
</div>
</div>
<div class="card-body">
<ngx-datatable
[rows]="inventory.items"
[count]="inventory.totalCount"
[list]="list"
default>
<ngx-datatable-column
[name]="'::Name' | abpLocalization"
prop="title">
</ngx-datatable-column>
<ngx-datatable-column
[name]="'::LiteratureType' | abpLocalization"
prop="type">
<ng-template let-row="row" ngx-datatable-cell-template>
{{ '::Enum:LiteratureType:' + row.type | abpLocalization }}
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column
[name]="'::PublicationDate' | abpLocalization"
prop="publishDate">
<ng-template let-row="row" ngx-datatable-cell-template>
{{ row.publishDate | date }}
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column
[name]="'::Cost' | abpLocalization"
prop="price">
<ng-template let-row="row" ngx-datatable-cell-template>
{{ row.price | currency }}
</ng-template>
</ngx-datatable-column>
</ngx-datatable>
</div>
</div>