如何在不将焦点设置在数据表上的情况下从 EXTERNAL SELECTION 获取 DataTable 到 select/highlight?
How to get DataTable to select/highlight from EXTERNAL SELECTION without setting focus on datatable?
这不是重复的 post,正如我所看到的,但找不到任何具有外部状态更改的内容。这几天我一直在断断续续地搜索这个话题。
我正在做的是以下内容。
我的 UI 上有数据表和地图。 DataTable 列出了地图上的数据点。
我可以在 DataTable 上 select 和 multi select,突出显示数据上的行 table 并与地图交互并绘制突出显示的数据点。
我遇到的问题是,当我将地图用于 select 时,DataTable 不会反映地图上与该数据点一起出现的 selected 行,直到我将鼠标悬停在我的 DataTable 上'假设在后台触发某种刷新。我不必在 DataTable 中单击或执行任何操作,它会自动触发,然后显示我在地图中 select 编辑的所有点。
html 页面为 [selected] 绑定的变量被正确调用并且它的值被设置,它只是不反映行上的高亮直到鼠标进入DataTable区域。我不需要点击或做任何事情来触发它,它会在鼠标进入该区域后自行触发。
此外,我还尝试手动设置 table selected 值,例如
this.tableRef.selected = this.newRowSelection;
所以我的问题是 如何让 DataTable 在我制作外部 selection 时自动显示?
我不想删除 table 和重绘 DataTable,因为我觉得这不会创建良好的用户体验。
感谢对此提出的所有意见。
============================================= ==========
更新:2020 年 3 月 11 日,星期三
因此,经过更多测试和调试后,我可以确认我确实将 datatable.selected 值设置为应该 selected 的 [] 行。
但是,在我将鼠标悬停在数据上之前,行不会突出显示table。
有人对如何让数据table自动突出显示有任何建议吗?
============================================= ==========
如果没有可重现的示例,很难确定,但我认为这是因为您正在更新 angular 范围之外的 属性,可能是点击地图的结果这不受 angular 方式的限制。
您可以阅读有关更改检测的内容 here。基本上,angular 会在浏览器事件(鼠标单击、鼠标悬停、按键事件...)、ajax 调用以及 setTimeout
和 [=13] 上触发对其了解的所有组件的更改检测=].
如果您在 angular 不知情的情况下更新了某些组件 属性(例如,通过将点击绑定到您的地图而不使用 nangular 的点击处理程序),angular(和你的数据table)不会知道它并且不会刷新直到下一次变化检测(这是数据table的鼠标悬停)
因此,如果您在 angular 之外进行此类更改,则需要使用以下两种方法之一再次通知 angular 到 运行 更改检测。
将您的修改包装在 setTimeout
中
setTimeout(()=> this.tableRef.selected = this.newRowSelection);
这将触发整个应用程序的更改检测
明确通知 angular 再次 运行 更改检测
import {ChangeDetectorRef} from '@angular/core';
constructor(private cdr: ChangeDetectorRef) {}
//....
this.tableRef.selected = this.newRowSelection;
this.cdr.detectChanges();
请注意,这将仅适用于您从中调用此方法的组件(和子组件)。因此,如果您的地图和数据 table 在同一个组件中,这应该会立即起作用。否则,您可以将某些事件从地图组件传播到包含 table 的组件以了解何时调用此方法。
您也可以直接在 angular 的区域内执行您的操作
import {NgZone} from '@angular/core';
constructor(private ngZone: NgZone) {}
//...
this.ngZone.run(() => this.tableRef.selected = this.newRowSelection);
我有一个解决方案并不完美,但它工作得很好!在更新所选行之前,只需重新分配您的行 this.rows = [...this.rows];
。它以某种方式触发数据的变化检测周期table。
如果您要动态更新 table 行,则每次获取新数据时都必须调用 refreshSelectedRow
(例如在数据更新订阅中)。
如果您 运行 没有重新分配的代码,它仍然可以工作,但仅适用于下一行数据更新(例如来自订阅),您很可能会将一个新数组对象分配给 this.rows
无论如何。根据您的数据更新频率,您可能会有延迟。
export class MapComponent {
SelectionType = SelectionType;
@ViewChild('myTable') table: any;
@Input() set selectedLotId(value: number | null) {
this._selected = value;
this.refreshSelectedRow();
}
private _selected: number | null;
rows: Lot[] = [];
constructor() {}
this.carParkSub$ = this.store.lots$.subscribe((lots) => {
this.rows = lots || [];
// needs to call here as well, cause in my case
// I am polling new data every 5s
this.refreshSelectedRow();
});
refreshSelectedRow() {
if (!this.table) {
return;
}
this.rows = [...this.rows]; //MUST BE RUN!. Otherwise datatable will not pick up changes to selected row;
let selected = this.rows.find((row) => row.id == this._selected);
this.table.selected = [];
if (selected) {
this.table.selected.push(selected);
}
}
}
<ngx-datatable #myTable
[rows]="rows"
[selectionType]="SelectionType.single"
[trackByProp]="'id'">
table columns and content here
</ngx-datatable>
在我的例子中,我使用 @Input()
道具从外部设置选定的行,而不是将绑定道具传递给模板中的 table 我使用编程方式 this.table.selected.push(selected);
注意:请记住,我从代码中删除了镇流器,因此简单的复制和粘贴将不起作用。
这不是重复的 post,正如我所看到的,但找不到任何具有外部状态更改的内容。这几天我一直在断断续续地搜索这个话题。
我正在做的是以下内容。
我的 UI 上有数据表和地图。 DataTable 列出了地图上的数据点。
我可以在 DataTable 上 select 和 multi select,突出显示数据上的行 table 并与地图交互并绘制突出显示的数据点。 我遇到的问题是,当我将地图用于 select 时,DataTable 不会反映地图上与该数据点一起出现的 selected 行,直到我将鼠标悬停在我的 DataTable 上'假设在后台触发某种刷新。我不必在 DataTable 中单击或执行任何操作,它会自动触发,然后显示我在地图中 select 编辑的所有点。
html 页面为 [selected] 绑定的变量被正确调用并且它的值被设置,它只是不反映行上的高亮直到鼠标进入DataTable区域。我不需要点击或做任何事情来触发它,它会在鼠标进入该区域后自行触发。
此外,我还尝试手动设置 table selected 值,例如
this.tableRef.selected = this.newRowSelection;
所以我的问题是 如何让 DataTable 在我制作外部 selection 时自动显示?
我不想删除 table 和重绘 DataTable,因为我觉得这不会创建良好的用户体验。
感谢对此提出的所有意见。
============================================= ==========
更新:2020 年 3 月 11 日,星期三
因此,经过更多测试和调试后,我可以确认我确实将 datatable.selected 值设置为应该 selected 的 [] 行。
但是,在我将鼠标悬停在数据上之前,行不会突出显示table。
有人对如何让数据table自动突出显示有任何建议吗?
============================================= ==========
如果没有可重现的示例,很难确定,但我认为这是因为您正在更新 angular 范围之外的 属性,可能是点击地图的结果这不受 angular 方式的限制。
您可以阅读有关更改检测的内容 here。基本上,angular 会在浏览器事件(鼠标单击、鼠标悬停、按键事件...)、ajax 调用以及 setTimeout
和 [=13] 上触发对其了解的所有组件的更改检测=].
如果您在 angular 不知情的情况下更新了某些组件 属性(例如,通过将点击绑定到您的地图而不使用 nangular 的点击处理程序),angular(和你的数据table)不会知道它并且不会刷新直到下一次变化检测(这是数据table的鼠标悬停)
因此,如果您在 angular 之外进行此类更改,则需要使用以下两种方法之一再次通知 angular 到 运行 更改检测。
将您的修改包装在 setTimeout
setTimeout(()=> this.tableRef.selected = this.newRowSelection);
这将触发整个应用程序的更改检测
明确通知 angular 再次 运行 更改检测
import {ChangeDetectorRef} from '@angular/core';
constructor(private cdr: ChangeDetectorRef) {}
//....
this.tableRef.selected = this.newRowSelection;
this.cdr.detectChanges();
请注意,这将仅适用于您从中调用此方法的组件(和子组件)。因此,如果您的地图和数据 table 在同一个组件中,这应该会立即起作用。否则,您可以将某些事件从地图组件传播到包含 table 的组件以了解何时调用此方法。
您也可以直接在 angular 的区域内执行您的操作
import {NgZone} from '@angular/core';
constructor(private ngZone: NgZone) {}
//...
this.ngZone.run(() => this.tableRef.selected = this.newRowSelection);
我有一个解决方案并不完美,但它工作得很好!在更新所选行之前,只需重新分配您的行 this.rows = [...this.rows];
。它以某种方式触发数据的变化检测周期table。
如果您要动态更新 table 行,则每次获取新数据时都必须调用 refreshSelectedRow
(例如在数据更新订阅中)。
如果您 运行 没有重新分配的代码,它仍然可以工作,但仅适用于下一行数据更新(例如来自订阅),您很可能会将一个新数组对象分配给 this.rows
无论如何。根据您的数据更新频率,您可能会有延迟。
export class MapComponent {
SelectionType = SelectionType;
@ViewChild('myTable') table: any;
@Input() set selectedLotId(value: number | null) {
this._selected = value;
this.refreshSelectedRow();
}
private _selected: number | null;
rows: Lot[] = [];
constructor() {}
this.carParkSub$ = this.store.lots$.subscribe((lots) => {
this.rows = lots || [];
// needs to call here as well, cause in my case
// I am polling new data every 5s
this.refreshSelectedRow();
});
refreshSelectedRow() {
if (!this.table) {
return;
}
this.rows = [...this.rows]; //MUST BE RUN!. Otherwise datatable will not pick up changes to selected row;
let selected = this.rows.find((row) => row.id == this._selected);
this.table.selected = [];
if (selected) {
this.table.selected.push(selected);
}
}
}
<ngx-datatable #myTable
[rows]="rows"
[selectionType]="SelectionType.single"
[trackByProp]="'id'">
table columns and content here
</ngx-datatable>
在我的例子中,我使用 @Input()
道具从外部设置选定的行,而不是将绑定道具传递给模板中的 table 我使用编程方式 this.table.selected.push(selected);
注意:请记住,我从代码中删除了镇流器,因此简单的复制和粘贴将不起作用。