Fading Coder

One Final Commit for the Last Sprint

Home > Tools > Content

Implementing a Book Catalog Interface in ABP Framework with Angular

Tools 1

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>

Related Articles

Efficient Usage of HTTP Client in IntelliJ IDEA

IntelliJ IDEA incorporates a versatile HTTP client tool, enabling developres to interact with RESTful services and APIs effectively with in the editor. This functionality streamlines workflows, replac...

Installing CocoaPods on macOS Catalina (10.15) Using a User-Managed Ruby

System Ruby on macOS 10.15 frequently fails to build native gems required by CocoaPods (for example, ffi), leading to errors like: ERROR: Failed to build gem native extension checking for ffi.h... no...

Resolve PhpStorm "Interpreter is not specified or invalid" on WAMP (Windows)

Symptom PhpStorm displays: "Interpreter is not specified or invalid. Press ‘Fix’ to edit your project configuration." This occurs when the IDE cannot locate a valid PHP CLI executable or when the debu...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.