angular - 如何在使用可观察对象作为数据源时更新角度数据表的行数、结果数和分页
问题描述
我正在尝试在我的 angular 7 应用程序中使用 angular-datatables 作为显示搜索结果的组件。
request-creation-component 创建一个搜索表单,当点击提交按钮时,使用 request-service 将 http Post 请求发送到后端,然后 request-creation-component 更新请求服务中的 observable -result-component 已订阅。
我的问题是用于显示结果的数据表在获得新结果时不会更新行数、结果数和分页按钮。
行数、结果数和分页按钮与第一次显示数据表时保持相同。
请求结果组件代码
requestResponse;
resultsAreFound = true;
constructor(private requestService: RequestService) { }
public dataTable: DataTable;
ngOnInit() {
this.dataTable = {headerRow : null, footerRow: null, dataRows: null };
this.requestService.currentSearchResult.subscribe(result => {
this.requestResponse = result;
if (result.length > 0) {
this.resultsAreFound = true;
// If it gets results, the datatable is assigned the new data.
this.dataTable.headerRow = Object.keys(this.requestResponse[0]);
this.dataTable.footerRow = Object.keys(this.requestResponse[0]);
this.dataTable.dataRows = this.requestResponse.map(function(i: { [s: string]: {}; } | ArrayLike<{}>) {
return Object.values(i);
});
} else {
// If it gets empty result, the datatable will be hidden and "0 results" message appears.
this.resultsAreFound = false;
}
});
}
ngAfterViewInit() {
$('#datatable').DataTable({
'pagingType': 'full_numbers',
'lengthMenu': [
[10, 25, 50, -1],
[10, 25, 50, 'All']
],
responsive: true,
language: {
search: '_INPUT_',
searchPlaceholder: 'Search records',
}
});
请求结果组件模板
<div class="main-content" style="margin-top: 50px;">
<div class="row">
<div class="col-md-12">
<div class="card">
<div [hidden]="resultsAreFound" class="card-header">
<h4 class="card-title">0 Resultats trouvées.</h4>
</div>
<div [hidden]="!resultsAreFound" class="card-body">
<div class="toolbar">
</div>
<table id="datatable" class="table table-striped table-bordered" cellspacing="0" width="100%">
<thead>
<tr>
<th>{{ dataTable.headerRow[0] }}</th>
<th>{{ dataTable.headerRow[1] }}</th>
<th>{{ dataTable.headerRow[2] }}</th>
<th>{{ dataTable.headerRow[3] }}</th>
<th>{{ dataTable.headerRow[4] }}</th>
<th class="disabled-sorting text-right">{{ dataTable.headerRow[5] }}</th>
</tr>
</thead>
<tfoot>
<tr>
<th>{{ dataTable.footerRow[0] }}</th>
<th>{{ dataTable.footerRow[1] }}</th>
<th>{{ dataTable.footerRow[2] }}</th>
<th>{{ dataTable.footerRow[3] }}</th>
<th>{{ dataTable.footerRow[4] }}</th>
<th>{{ dataTable.footerRow[5] }}</th>
</tr>
</tfoot>
<tbody>
<tr *ngFor="let row of dataTable.dataRows">
<td>{{row[0]}}</td>
<td>{{row[1]}}</td>
<td>{{row[2]}}</td>
<td>{{row[3]}}</td>
<td>{{row[4]}}</td>
<td class="text-right">
<a href="#" class="btn btn-danger btn-link btn-icon btn-sm remove"><i class="fa fa-times"></i></a>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end content-->
</div>
<!-- end card -->
</div>
<!-- end col-md-12 -->
</div>
<!-- end row -->
</div>
解决方案
angular-datatable (datatables.net 库的包装器)不支持动态数据源,因此在创建表时无法更改数据。
因此,为了解决这个问题,我必须在每次数据更改时重新创建表。
这是代码,request-results.component.ts 文件:
import { Component, OnInit, OnDestroy, AfterViewInit, ViewChild } from '@angular/core';
import { RequestService } from '../services/request.service';
import { Subject } from 'rxjs/internal/Subject';
import { DataTableDirective } from 'angular-datatables';
declare var $: any;
declare interface DataTable {
headerRow: string[];
dataRows: string[][];
}
@Component({
selector: 'app-request-results',
templateUrl: './request-results.component.html'
})
export class RequestResultsComponent implements OnDestroy, AfterViewInit, OnInit {
@ViewChild(DataTableDirective)
dtElement: DataTableDirective;
public hideTheResults = false;
private notFirstTime = false; // if the data table is going to be used again with new data, it has to be recreated
requestResponse;
resultsAreFound = true;
dtOptions: DataTables.Settings = {
columnDefs: [ { orderable: false, targets: [4, 5] } ],
retrieve: true,
autoWidth: true,
pagingType: 'full_numbers',
lengthMenu : [
[10, 25, 50, -1],
[10, 25, 50, 'All']
],
responsive: true,
language: {
search: '_INPUT_',
searchPlaceholder: 'Search records',
}};
dtTrigger = new Subject();
public dataTable: DataTable;
constructor(private requestService: RequestService) { }
ngOnInit() {
this.dataTable = {headerRow : null, footerRow: null, dataRows: null };
this.dataTable.headerRow = ['Col1', 'Col2', 'Col3', 'Col4', 'Col5'];
this.requestService.currentSearchResult.subscribe(result => {
this.requestResponse = result;
if (result.length > 0) {
const table = $('#datatable').DataTable();
table.destroy();
this.resultsAreFound = true;
if (this.notFirstTime) {
this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
dtInstance.destroy();
});
}
this.notFirstTime = true;
this.dataTable.dataRows = this.requestResponse.map(
function(i: { [s: string]: {}; } | ArrayLike<{}>) { return Object.values(i);
});
this.dtTrigger.next();
} else {
this.notFirstTime = true;
this.resultsAreFound = false;
}
});
}
ngOnDestroy(): void {
this.dtTrigger.unsubscribe();
}
ngAfterViewInit() {
this.dtTrigger.next();
}
和 request-results.component.html 文件:
<div class="main-content" style="margin-top: 50px; padding-left: 0px; padding-right: 0px">
<div class="row">
<div class="col-md-12">
<div class="card">
<div [hidden]="resultsAreFound" class="card-header">
<h4 class="card-title">0 Resultats trouvées.</h4>
</div>
<div [hidden]="!resultsAreFound || hideTheResults" class="card-body">
<h4 class="card-title">Profils trouvées:</h4>
<div class="toolbar">
<!-- Here you can write extra buttons/actions for the toolbar -->
</div>
<table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="table table-striped table-bordered">
<thead>
<tr>
<th>{{ dataTable.headerRow[0] }}<span></span></th>
<th>{{ dataTable.headerRow[1] }}<span></span></th>
<th>{{ dataTable.headerRow[2] }}<span></span></th>
<th>{{ dataTable.headerRow[3] }}<span></span></th>
<th>{{ dataTable.headerRow[4] }}<span></span></th>
<th><span></span></th>
</tr>
</thead>
<tfoot>
<tr>
<th>{{ dataTable.footerRow[0] }}</th>
<th>{{ dataTable.footerRow[1] }}</th>
<th>{{ dataTable.footerRow[2] }}</th>
<th>{{ dataTable.footerRow[3] }}</th>
<th>{{ dataTable.footerRow[4] }}</th>
<th></th>
</tr>
</tfoot>
<tbody>
<tr *ngFor="let row of dataTable.dataRows">
<td>{{row[0]}}</td>
<td>{{row[1]}}</td>
<td>{{row[2]}}</td>
<td>{{row[3]}}</td>
<td>
<a class="btn btn-info btn-link btn-icon btn-sm like" href="{{row[4]}}" title="LinkedIn"><i class="fa fa-linkedin"></i></a>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end content-->
</div>
<!-- end card -->
</div>
<!-- end col-md-12 -->
</div>
<!-- end row -->
推荐阅读
- vb.net - VB.NET 2010 - 用于 FTPS 的 WinSCP 包
- jquery - 如何使用内联 jquery 迭代组合框中的响应值?-姜戈
- java - Apache Camel 自定义服务和关闭
- flask - 无法通过apt安装任何东西。没有名为“flask”的模块
- swift - 将 VNCoreMLFeatureValueObservation 转换为 VNDetectedObjectObservation
- html - 指向 url 时的 href vs html 标签
- matlab - Body of this Matlab function works, but not the function itself (interp1 error)
- salesforce - 在 Salesforce 中重现基于时间的工作流程
- ruby-on-rails - 如何在rails的active_admin中添加一个动作
- r - 在R中循环变量