JHipster/Angular - 如何处理 generator/../entity-management.component.ts.ejs 中 transition() 的删除(在 JHipster 6.6.0 中)
JHipster/Angular - How to deal with removal of transition() in generator/../entity-management.component.ts.ejs (in JHipster 6.6.0)
我是从使用 JHipster 6.5.0 的《Full Stack Development with JHipster (Second Edition)》这本书开始学习 JHipster 的。
在第 5 章“自定义和进一步开发”中,默认的 table 视图被替换为列表。为了恢复排序功能,作者加入了以下 jhiSort 指令(第 134 页):
jhiSort [(predicate)]="predicate" [(ascending)]="reverse" [callback]="transition.bind(this)"
作为此代码段的一部分:
<div class="mb-2 d-flex justify-content-end align-items-center">
<span class="mx-2 col-1">Sort by</span>
<div class="btn-group" role="group" jhiSort [(predicate)]="predicate" [(ascending)]="reverse" [callback]="transition.bind(this)">
<button type="button" class="btn btn-light" jhiSortBy="name">
<span class="d-flex">
<span jhiTranslate="storeApp.product.name">Name</span>
<fa-icon [icon]="'sort'"></fa-icon>
</span>
</button>
...
</div>
</div>
因此无法解析“reverse”和“transition.bind(this)”。我将“product.components.ts”文件与本书源代码中的文件进行了比较,发现我的文件
中不存在“transition()”函数
product.components.ts (JHipster 7.0.0.)
import { Component, OnInit } from '@angular/core';
import { HttpHeaders, HttpResponse } from '@angular/common/http';
import { ActivatedRoute, Router } from '@angular/router';
import { combineLatest } from 'rxjs';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { IProduct } from '../product.model';
import { ITEMS_PER_PAGE } from 'app/config/pagination.constants';
import { ProductService } from '../service/product.service';
import { ProductDeleteDialogComponent } from '../delete/product-delete-dialog.component';
import { DataUtils } from 'app/core/util/data-util.service';
@Component({
selector: 'jhi-product',
templateUrl: './product.component.html',
})
export class ProductComponent implements OnInit {
products?: IProduct[];
isLoading = false;
totalItems = 0;
itemsPerPage = ITEMS_PER_PAGE;
page?: number;
predicate!: string;
ascending!: boolean;
ngbPaginationPage = 1;
constructor(
protected productService: ProductService,
protected activatedRoute: ActivatedRoute,
protected dataUtils: DataUtils,
protected router: Router,
protected modalService: NgbModal
) {}
loadPage(page?: number, dontNavigate?: boolean): void {
this.isLoading = true;
const pageToLoad: number = page ?? this.page ?? 1;
this.productService
.query({
page: pageToLoad - 1,
size: this.itemsPerPage,
sort: this.sort(),
})
.subscribe(
(res: HttpResponse<IProduct[]>) => {
this.isLoading = false;
this.onSuccess(res.body, res.headers, pageToLoad, !dontNavigate);
},
() => {
this.isLoading = false;
this.onError();
}
);
}
ngOnInit(): void {
this.handleNavigation();
}
trackId(index: number, item: IProduct): number {
return item.id!;
}
byteSize(base64String: string): string {
return this.dataUtils.byteSize(base64String);
}
openFile(base64String: string, contentType: string | null | undefined): void {
return this.dataUtils.openFile(base64String, contentType);
}
delete(product: IProduct): void {
const modalRef = this.modalService.open(ProductDeleteDialogComponent, { size: 'lg', backdrop: 'static' });
modalRef.componentInstance.product = product;
// unsubscribe not needed because closed completes on modal close
modalRef.closed.subscribe(reason => {
if (reason === 'deleted') {
this.loadPage();
}
});
}
protected sort(): string[] {
const result = [this.predicate + ',' + (this.ascending ? 'asc' : 'desc')];
if (this.predicate !== 'id') {
result.push('id');
}
return result;
}
protected handleNavigation(): void {
combineLatest([this.activatedRoute.data, this.activatedRoute.queryParamMap]).subscribe(([data, params]) => {
const page = params.get('page');
const pageNumber = page !== null ? +page : 1;
const sort = (params.get('sort') ?? data['defaultSort']).split(',');
const predicate = sort[0];
const ascending = sort[1] === 'asc';
if (pageNumber !== this.page || predicate !== this.predicate || ascending !== this.ascending) {
this.predicate = predicate;
this.ascending = ascending;
this.loadPage(pageNumber, true);
}
});
}
protected onSuccess(data: IProduct[] | null, headers: HttpHeaders, page: number, navigate: boolean): void {
this.totalItems = Number(headers.get('X-Total-Count'));
this.page = page;
if (navigate) {
this.router.navigate(['/product'], {
queryParams: {
page: this.page,
size: this.itemsPerPage,
sort: this.predicate + ',' + (this.ascending ? 'asc' : 'desc'),
},
});
}
this.products = data ?? [];
this.ngbPaginationPage = this.page;
}
protected onError(): void {
this.ngbPaginationPage = this.page ?? 1;
}
}
在作者的或者JHipster 6.5.0生成的文件中存在:
product.components.ts (JHipster 6.5.0)
import { Component, OnInit, OnDestroy } from '@angular/core';
import { HttpHeaders, HttpResponse } from '@angular/common/http';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { JhiEventManager, JhiParseLinks, JhiDataUtils } from 'ng-jhipster';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { IProduct } from 'app/shared/model/product.model';
import { ITEMS_PER_PAGE } from 'app/shared/constants/pagination.constants';
import { ProductService } from './product.service';
import { ProductDeleteDialogComponent } from './product-delete-dialog.component';
@Component({
selector: 'jhi-product',
templateUrl: './product.component.html'
})
export class ProductComponent implements OnInit, OnDestroy {
products: IProduct[];
error: any;
success: any;
eventSubscriber: Subscription;
routeData: any;
links: any;
totalItems: any;
itemsPerPage: any;
page: any;
predicate: any;
previousPage: any;
reverse: any;
constructor(
protected productService: ProductService,
protected parseLinks: JhiParseLinks,
protected activatedRoute: ActivatedRoute,
protected dataUtils: JhiDataUtils,
protected router: Router,
protected eventManager: JhiEventManager,
protected modalService: NgbModal
) {
this.itemsPerPage = ITEMS_PER_PAGE;
this.routeData = this.activatedRoute.data.subscribe(data => {
this.page = data.pagingParams.page;
this.previousPage = data.pagingParams.page;
this.reverse = data.pagingParams.ascending;
this.predicate = data.pagingParams.predicate;
});
}
loadAll() {
this.productService
.query({
page: this.page - 1,
size: this.itemsPerPage,
sort: this.sort()
})
.subscribe((res: HttpResponse<IProduct[]>) => this.paginateProducts(res.body, res.headers));
}
loadPage(page: number) {
if (page !== this.previousPage) {
this.previousPage = page;
this.transition();
}
}
transition() {
this.router.navigate(['/product'], {
queryParams: {
page: this.page,
size: this.itemsPerPage,
sort: this.predicate + ',' + (this.reverse ? 'asc' : 'desc')
}
});
this.loadAll();
}
clear() {
this.page = 0;
this.router.navigate([
'/product',
{
page: this.page,
sort: this.predicate + ',' + (this.reverse ? 'asc' : 'desc')
}
]);
this.loadAll();
}
ngOnInit() {
this.loadAll();
this.registerChangeInProducts();
}
ngOnDestroy() {
this.eventManager.destroy(this.eventSubscriber);
}
trackId(index: number, item: IProduct) {
return item.id;
}
byteSize(field) {
return this.dataUtils.byteSize(field);
}
openFile(contentType, field) {
return this.dataUtils.openFile(contentType, field);
}
registerChangeInProducts() {
this.eventSubscriber = this.eventManager.subscribe('productListModification', () => this.loadAll());
}
delete(product: IProduct) {
const modalRef = this.modalService.open(ProductDeleteDialogComponent, { size: 'lg', backdrop: 'static' });
modalRef.componentInstance.product = product;
}
sort() {
const result = [this.predicate + ',' + (this.reverse ? 'asc' : 'desc')];
if (this.predicate !== 'id') {
result.push('id');
}
return result;
}
protected paginateProducts(data: IProduct[], headers: HttpHeaders) {
this.links = this.parseLinks.parse(headers.get('link'));
this.totalItems = parseInt(headers.get('X-Total-Count'), 10);
this.products = data;
}
}
简而言之:
今天,我能够追踪 transition() 函数不存在的原因,直到 JHipster 6.6.0 的 221 个已关闭工单和合并拉取请求之一:
修复 Angular 中的实体分页
kaidohallik 的#10959 已于 2019 年 12 月 19 日合并
https://github.com/jhipster/generator-jhipster/pull/10959
尽管知道更改的来源,但我无法调整 jhiSort 指令来反映更改。
有人可以告诉我如何调整 jhiSort 指令以便正确排序数据吗?
非常感谢您的支持。
毕竟,答案很简单,因为它已成为“product.component.html”页面的一部分 ,在 之前 table 视图已被替换列表视图。
HTML tr 标签具有以下 jhiSort 指令
<tr jhiSort [(predicate)]="predicate" [(ascending)]="ascending" [callback]="loadPage.bind(this)">
如您所见,所有要做的就是使用“升序”而不是“反向”和“加载页面”而不是“转换”。
通过这两项更改,排序工作正常。
我是从使用 JHipster 6.5.0 的《Full Stack Development with JHipster (Second Edition)》这本书开始学习 JHipster 的。
在第 5 章“自定义和进一步开发”中,默认的 table 视图被替换为列表。为了恢复排序功能,作者加入了以下 jhiSort 指令(第 134 页):
jhiSort [(predicate)]="predicate" [(ascending)]="reverse" [callback]="transition.bind(this)"
作为此代码段的一部分:
<div class="mb-2 d-flex justify-content-end align-items-center">
<span class="mx-2 col-1">Sort by</span>
<div class="btn-group" role="group" jhiSort [(predicate)]="predicate" [(ascending)]="reverse" [callback]="transition.bind(this)">
<button type="button" class="btn btn-light" jhiSortBy="name">
<span class="d-flex">
<span jhiTranslate="storeApp.product.name">Name</span>
<fa-icon [icon]="'sort'"></fa-icon>
</span>
</button>
...
</div>
</div>
因此无法解析“reverse”和“transition.bind(this)”。我将“product.components.ts”文件与本书源代码中的文件进行了比较,发现我的文件
中不存在“transition()”函数product.components.ts (JHipster 7.0.0.)
import { Component, OnInit } from '@angular/core';
import { HttpHeaders, HttpResponse } from '@angular/common/http';
import { ActivatedRoute, Router } from '@angular/router';
import { combineLatest } from 'rxjs';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { IProduct } from '../product.model';
import { ITEMS_PER_PAGE } from 'app/config/pagination.constants';
import { ProductService } from '../service/product.service';
import { ProductDeleteDialogComponent } from '../delete/product-delete-dialog.component';
import { DataUtils } from 'app/core/util/data-util.service';
@Component({
selector: 'jhi-product',
templateUrl: './product.component.html',
})
export class ProductComponent implements OnInit {
products?: IProduct[];
isLoading = false;
totalItems = 0;
itemsPerPage = ITEMS_PER_PAGE;
page?: number;
predicate!: string;
ascending!: boolean;
ngbPaginationPage = 1;
constructor(
protected productService: ProductService,
protected activatedRoute: ActivatedRoute,
protected dataUtils: DataUtils,
protected router: Router,
protected modalService: NgbModal
) {}
loadPage(page?: number, dontNavigate?: boolean): void {
this.isLoading = true;
const pageToLoad: number = page ?? this.page ?? 1;
this.productService
.query({
page: pageToLoad - 1,
size: this.itemsPerPage,
sort: this.sort(),
})
.subscribe(
(res: HttpResponse<IProduct[]>) => {
this.isLoading = false;
this.onSuccess(res.body, res.headers, pageToLoad, !dontNavigate);
},
() => {
this.isLoading = false;
this.onError();
}
);
}
ngOnInit(): void {
this.handleNavigation();
}
trackId(index: number, item: IProduct): number {
return item.id!;
}
byteSize(base64String: string): string {
return this.dataUtils.byteSize(base64String);
}
openFile(base64String: string, contentType: string | null | undefined): void {
return this.dataUtils.openFile(base64String, contentType);
}
delete(product: IProduct): void {
const modalRef = this.modalService.open(ProductDeleteDialogComponent, { size: 'lg', backdrop: 'static' });
modalRef.componentInstance.product = product;
// unsubscribe not needed because closed completes on modal close
modalRef.closed.subscribe(reason => {
if (reason === 'deleted') {
this.loadPage();
}
});
}
protected sort(): string[] {
const result = [this.predicate + ',' + (this.ascending ? 'asc' : 'desc')];
if (this.predicate !== 'id') {
result.push('id');
}
return result;
}
protected handleNavigation(): void {
combineLatest([this.activatedRoute.data, this.activatedRoute.queryParamMap]).subscribe(([data, params]) => {
const page = params.get('page');
const pageNumber = page !== null ? +page : 1;
const sort = (params.get('sort') ?? data['defaultSort']).split(',');
const predicate = sort[0];
const ascending = sort[1] === 'asc';
if (pageNumber !== this.page || predicate !== this.predicate || ascending !== this.ascending) {
this.predicate = predicate;
this.ascending = ascending;
this.loadPage(pageNumber, true);
}
});
}
protected onSuccess(data: IProduct[] | null, headers: HttpHeaders, page: number, navigate: boolean): void {
this.totalItems = Number(headers.get('X-Total-Count'));
this.page = page;
if (navigate) {
this.router.navigate(['/product'], {
queryParams: {
page: this.page,
size: this.itemsPerPage,
sort: this.predicate + ',' + (this.ascending ? 'asc' : 'desc'),
},
});
}
this.products = data ?? [];
this.ngbPaginationPage = this.page;
}
protected onError(): void {
this.ngbPaginationPage = this.page ?? 1;
}
}
在作者的或者JHipster 6.5.0生成的文件中存在:
product.components.ts (JHipster 6.5.0)
import { Component, OnInit, OnDestroy } from '@angular/core';
import { HttpHeaders, HttpResponse } from '@angular/common/http';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { JhiEventManager, JhiParseLinks, JhiDataUtils } from 'ng-jhipster';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { IProduct } from 'app/shared/model/product.model';
import { ITEMS_PER_PAGE } from 'app/shared/constants/pagination.constants';
import { ProductService } from './product.service';
import { ProductDeleteDialogComponent } from './product-delete-dialog.component';
@Component({
selector: 'jhi-product',
templateUrl: './product.component.html'
})
export class ProductComponent implements OnInit, OnDestroy {
products: IProduct[];
error: any;
success: any;
eventSubscriber: Subscription;
routeData: any;
links: any;
totalItems: any;
itemsPerPage: any;
page: any;
predicate: any;
previousPage: any;
reverse: any;
constructor(
protected productService: ProductService,
protected parseLinks: JhiParseLinks,
protected activatedRoute: ActivatedRoute,
protected dataUtils: JhiDataUtils,
protected router: Router,
protected eventManager: JhiEventManager,
protected modalService: NgbModal
) {
this.itemsPerPage = ITEMS_PER_PAGE;
this.routeData = this.activatedRoute.data.subscribe(data => {
this.page = data.pagingParams.page;
this.previousPage = data.pagingParams.page;
this.reverse = data.pagingParams.ascending;
this.predicate = data.pagingParams.predicate;
});
}
loadAll() {
this.productService
.query({
page: this.page - 1,
size: this.itemsPerPage,
sort: this.sort()
})
.subscribe((res: HttpResponse<IProduct[]>) => this.paginateProducts(res.body, res.headers));
}
loadPage(page: number) {
if (page !== this.previousPage) {
this.previousPage = page;
this.transition();
}
}
transition() {
this.router.navigate(['/product'], {
queryParams: {
page: this.page,
size: this.itemsPerPage,
sort: this.predicate + ',' + (this.reverse ? 'asc' : 'desc')
}
});
this.loadAll();
}
clear() {
this.page = 0;
this.router.navigate([
'/product',
{
page: this.page,
sort: this.predicate + ',' + (this.reverse ? 'asc' : 'desc')
}
]);
this.loadAll();
}
ngOnInit() {
this.loadAll();
this.registerChangeInProducts();
}
ngOnDestroy() {
this.eventManager.destroy(this.eventSubscriber);
}
trackId(index: number, item: IProduct) {
return item.id;
}
byteSize(field) {
return this.dataUtils.byteSize(field);
}
openFile(contentType, field) {
return this.dataUtils.openFile(contentType, field);
}
registerChangeInProducts() {
this.eventSubscriber = this.eventManager.subscribe('productListModification', () => this.loadAll());
}
delete(product: IProduct) {
const modalRef = this.modalService.open(ProductDeleteDialogComponent, { size: 'lg', backdrop: 'static' });
modalRef.componentInstance.product = product;
}
sort() {
const result = [this.predicate + ',' + (this.reverse ? 'asc' : 'desc')];
if (this.predicate !== 'id') {
result.push('id');
}
return result;
}
protected paginateProducts(data: IProduct[], headers: HttpHeaders) {
this.links = this.parseLinks.parse(headers.get('link'));
this.totalItems = parseInt(headers.get('X-Total-Count'), 10);
this.products = data;
}
}
简而言之: 今天,我能够追踪 transition() 函数不存在的原因,直到 JHipster 6.6.0 的 221 个已关闭工单和合并拉取请求之一: 修复 Angular 中的实体分页 kaidohallik 的#10959 已于 2019 年 12 月 19 日合并 https://github.com/jhipster/generator-jhipster/pull/10959
尽管知道更改的来源,但我无法调整 jhiSort 指令来反映更改。
有人可以告诉我如何调整 jhiSort 指令以便正确排序数据吗?
非常感谢您的支持。
毕竟,答案很简单,因为它已成为“product.component.html”页面的一部分 ,在 之前 table 视图已被替换列表视图。
HTML tr 标签具有以下 jhiSort 指令
<tr jhiSort [(predicate)]="predicate" [(ascending)]="ascending" [callback]="loadPage.bind(this)">
如您所见,所有要做的就是使用“升序”而不是“反向”和“加载页面”而不是“转换”。
通过这两项更改,排序工作正常。