1

使用清晰的数据网格 2.3 版看到一个问题,如果用户开始在数据网格列过滤器的输入字段中输入内容,一旦按下一个键,过滤器输入就会自动聚焦。

由于数据网格是分页的并且是服务器驱动的,这会导致 API 在去抖动时间之后一旦按下一个键就会被触发。

输入字段之外的自动焦点导致过滤器只有一个字符,并且 API 被触发,因为 debouce 只有 800。

已经查看了清晰 github 上的任何报告问题,看起来不像它报告的或任何有类似问题的人。

预期的行为应该是输入焦点不应该发生,直到用户将光标移开或按下回车,这是应该在之后调用 api 的去抖动应该启动的时候。

HTML:
<clr-datagrid
   (clrDgRefresh)= refreshDataGrid($event)>
...
</clr-datagrid>

TS Component:
debouncer = new Subject<any>();

ngOnInit() {

  this.debouncer.asObservable().pipe(
    debounceTime(800)
  ).subscribe(state => {
     // do something here.. like call an API to filter the grid.
  })
}

refreshDataGrid(state) {
 this.debouncer.next(state);
}

任何帮助表示赞赏。

4

2 回答 2

0

不幸的是,我认为我们设计了数据网格以在每个过滤器值更改时发出更改,并在消费者认为合适的情况下在应用程序端进行去抖动。

也就是说,有可能完成你所描述的。我已经根据事件实施了一个快速而肮脏的守卫,但可能有更好的方法。我将在此处添加代码片段,并在最后添加指向正在运行的 stackblitz 的链接。

使用去抖动器,您走在正确的轨道上。但是我们不需要随着时间去抖动,我们只需要在某些事件上“去抖动”。

如果我们使用@HostListener 对过滤器输入的点击进行去抖动,而不是随着时间去抖动呢?(我将把它作为练习留给您为 focusin 事件实现一个 HostListener,因为 focusin 气泡上升而 blur 没有)。为此,我们需要:

  1. 可以在过滤器输入上听到 keydown.enter 事件的 Hostlistener
  2. 防止请求的守卫
  3. 在用户输入文本时存储数据网格状态的属性

一般来说,代码需要:

  1. 除非有指示,否则在组件启动时获取数据,而不是之后
  2. 跟踪从数据网格发出的状态事件
  3. 听 keydown.enter 事件(以及任何其他事件,如过滤器输入焦点输出 - 因为它会冒泡,不像模糊)
  4. 检查事件是否在数据网格过滤器输入上生成
  5. 解雇警卫
  6. 提出请求
  7. 重新招募守卫

这是一个粗略的尝试:

export class DatagridFullDemo {
    refreshGuard = true; // init to true to get first run data
    debouncer = new Subject<any>(); // this is now an enter key debouncer
    datagridState: ClrDatagridStateInterface; // a place to store datagrid state as it is emitted

    ngOnInit() {
        // subscribe to the debouncer and pass the state to the doRefresh function
      this.debouncer.asObservable().subscribe(state => {
        this.doRefresh(state);
      });
    }

    // a private function that takes a datagrid state
    private doRefresh(state: ClrDatagridStateInterface) {
        // Guard against refreshes ad only run them when true
      if (this.refreshGuard) {
        this.loading = true;
        const filters: { [prop: string]: any[] } = {};
        console.log("refresh called");
        if (state.filters) {
          for (const filter of state.filters) {
            const { property, value } = <{ property: string; value: string }>(
              filter
            );
            filters[property] = [value];
          }
        }
        this.inventory
          .filter(filters)
          .sort(<{ by: string; reverse: boolean }>state.sort)
          .fetch(state.page.from, state.page.size)
          .then((result: FetchResult) => {
            this.users = result.users;
            this.total = result.length;
            this.loading = false;
            this.selectedUser = this.users[1];
            // Set the guard back to false to prevent requests
            this.refreshGuard = false;
          });
      }
    }

    // Listen to keydown.enter events
    @HostListener("document:keydown.enter", ["$event"]) enterKeydownHandler(
      event: KeyboardEvent
    ) {
        // Use a host listener that checks the event element parent to make sure its a datagrid filter
      const eventSource: HTMLElement = event.srcElement as HTMLElement;
      const parentElement = eventSource.parentElement as HTMLElement;
      if (parentElement.classList.contains("datagrid-filter")) {
        // tell our guard its ok to refresh
        this.refreshGuard = true;
        // pass the latest state to the debouncer to make the request
        this.debouncer.next(this.datagridState);
      }
    }

    refresh(state: ClrDatagridStateInterface) {
      this.datagridState = state;
      this.debouncer.next(state);
    }
  }

这是一个有效的堆栈闪电战: https ://stackblitz.com/edit/so-60980488

于 2020-04-02T01:16:31.547 回答
0

目前我正在破解我的组件,以确保在用户这样做之前焦点不会丢失在输入字段上。

refreshDataGrid(state) {
   const isClrFilterInputField = document.querySelector('.datagrid-filter .clr-input');
   if (isClrFilterInputField instanceof HTMLElement) {
     isClrFilterInputField.focus();
   }
   this.debouncer.next(state);
}

这仍然不是一个干净的答案,但据我搜索,这似乎是清晰数据网格本身的问题,直到我听到有人给出更干净的答案。

升级版本很可能已修复此问题。还要检查一下。

于 2020-04-01T21:29:28.317 回答