列表操作指南
ListService 是一个实用服务,可轻松实现分页、排序和搜索功能。
快速开始
ListService 未在根注入器中提供。这种方式可以在组件销毁时自动清理所有订阅。您可以使用可选的 LIST_QUERY_DEBOUNCE_TIME 令牌来调整防抖行为。
import { ListService } from '@abp/ng.core';
import { BookDto } from '../models';
import { BookService } from '../services';
import { inject } from '@angular/core';
@Component({
/* 类元数据 */
providers: [
// [必需]
ListService,
// [可选]
// 如需不同的防抖时间可提供此令牌
// 默认值为300,不能为0,不建议低于100
{ provide: LIST_QUERY_DEBOUNCE_TIME, useValue: 500 },
],
template: `
`,
})
class BookComponent {
items: BookDto[] = [];
count = 0;
public readonly list = inject(ListService);
private bookService = inject(BookService);
constructor() {
// 在此处修改 ListService 默认值
this.list.maxResultCount = 20;
}
ngOnInit() {
// 接收查询参数并返回可观察对象的函数
const bookStreamCreator = query => this.bookService.getList(query);
this.list.hookToQuery(bookStreamCreator).subscribe(
response => {
this.items = response.items;
this.count = response.count;
// 如果使用 OnPush 变更检测策略,
// 请在此处调用 ChangeDetectorRef 的 detectChanges 方法
}
); // 订阅会在销毁时自动清理
}
}
注意到
list是public且readonly了吗?这是因为我们将在组件模板中直接使用ListService。这可能被视为反模式,但实现起来更快。您也可以使用公共组件成员来暴露ListService实例。
将 ListService 绑定到 ngx-datatable 的方式如下:
<ngx-datatable
[rows]="items"
[count]="count"
[list]="list"
default
>
<!-- 列模板 -->
</ngx-datatable>
使用自定义变量扩展查询
您可以扩展 ListService 的 hookToQuery 方法的查询参数。
首先,应按如下所示将自己的类型传递给 ListService:
public readonly list = inject(ListService<BooksSearchParamsDto>);
然后按以下方式更新 bookStreamCreator 常量:
const bookStreamCreator = (query) => this.bookService.getList({...query, name: '名称'});
您也可以创建自己的参数对象。
定义如下变量:
booksSearchParams = {} as BooksSearchParamsDto;
更新 bookStreamCreator 常量:
const bookStreamCreator = (query) => this.bookService.getList({...query, ...this.booksSearchParams});
然后在 HTML 中添加输入框:
<div class="form-group">
<input
class="form control"
placeholder="名称"
(keyup.enter)="list.get()"
[(ngModel)]="booksSearchParams.name"
/>
</div>
当您调用 this.list.get() 方法时,ListService 会发出 hookToQuery 流。
与可观察对象结合使用
您也可以结合使用 Angular 的 AsyncPipe。以下是几种可能的方式:
book$ = this.list.hookToQuery(query => this.bookService.getListByInput(query));
<!-- 模板简化表示 -->
<ngx-datatable
[rows]="(book$ | async)?.items || []"
[count]="(book$ | async)?.totalCount || 0"
[list]="list"
default
>
<!-- 列模板 -->
</ngx-datatable>
<!-- 无需担心,只会发出一个请求 -->
处理请求状态
为处理请求状态,ListService 提供了 requestStatus$ 可观察对象。该可观察对象会发出请求的当前状态,可能为以下值之一:idle(空闲)、loading(加载中)、success(成功)或 error(错误)。这些状态让您可以基于请求状态轻松管理 UI 流程。
import { ListService } from '@abp/ng.core';
import { AsyncPipe } from '@angular/common';
import { Component, inject } from '@angular/core';
import { BookDto, BooksService } from './books.service';
@Component({
selector: 'app-books',
templateUrl: './books.component.html',
providers: [ListService, BooksService],
imports: [AsyncPipe],
})
export class BooksComponent {
list = inject(ListService);
booksService = inject(BooksService);
items = new Array<BookDto>();
count = 0;
// 这是一个可观察变量
requestStatus$ = this.list.requestStatus$;
ngOnInit(): void {
this.list
.hookToQuery(() => this.booksService.getList())
.subscribe(response => {
this.items = response.items;
this.count = response.totalCount;
});
}
}
<div class="card">
<div class="card-header">
@if (requestStatus$ | async; as status) {
@switch (status) {
@case ('loading') {
<div style="height: 62px">
<div class="spinner-border" role="status" id="loading">
<span class="visually-hidden">加载中...</span>
</div>
</div>
}
@case ('error') {
<h4>发生错误</h4>
}
@default {
<h4>书籍列表</h4>
}
}
}
</div>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>名称</th>
</tr>
</thead>
<tbody>
@for (book of items; track book.id) {
<tr>
<td>{{ book.id }}</td>
<td>{{ book.name }}</td>
</tr>
}
</tbody>
</table>
</div>
如何在创建/更新/删除时刷新表格
ListService 暴露了 get 方法来使用当前查询触发请求。因此,基本上,当创建、更新或删除操作完成时,您可以调用 this.list.get();,它将再次调用已连接的流创建器。
this.bookService.createByInput(form.value)
.subscribe(() => {
this.list.get();
// 其他订阅逻辑
});
如何在表格中实现服务端搜索
ListService 暴露了 filter 属性,该属性将使用当前查询和给定的搜索字符串触发请求。您只需将其与输入元素进行双向绑定即可。
<!-- 简化表示 -->
<input type="text" name="search" [(ngModel)]="list.filter">
ABP 没有内置的过滤机制。您需要自行实现并在后端处理 filter 属性。
抠丁客



