角度滚动指令未触发

问题描述 投票:0回答:1

一旦下拉列表中的滚动条到达底部,我想获得一个 console.log() 以实现无限滚动/“加载更多”功能: enter image description here

在下面的代码中,我创建了一个

ScrollEndDirective
指令,它将仅发送到组件文件:

export class ScrollEndDirective {
  @Output() scrolledToEnd = new EventEmitter<boolean>();

  constructor(private el: ElementRef) {
    console.log('constructor logger'); // <- this is logging
  }

  @HostListener('scroll', ['$event'])
  onScroll(event: Event): void {
    const element = this.el.nativeElement as HTMLElement;
    console.log(element); // <-- this is not even logging

    if (element.scrollHeight - element.scrollTop === element.clientHeight) {
      this.scrolledToEnd.emit(true);
    } else {
      this.scrolledToEnd.emit(false);
    }
  }
}

下面是组件文件:

@Component({
  selector: 'nz-demo-auto-complete-options',
  template: `
    <div class="example-input">
      <input
        placeholder="input here"
        nz-input
        [(ngModel)]="inputValue"
        (input)="onInputChange($event)"
        [nzAutocomplete]="auto"
      />
      <nz-autocomplete #auto scrollEnd (scrolledToEnd)="onScrollEnd($event)">
        <nz-auto-option *ngFor="let option of options" [nzValue]="option.name">{{ option.name }}</nz-auto-option>
      </nz-autocomplete>
    </div>
  `,
})
export class NzDemoAutoCompleteOptionsComponent {
  inputValue?: string;
  options: string[] = [];
  private searchSubject = new Subject<string>();

  constructor(private http: HttpClient) {
    this.searchSubject
      .pipe(
        // debounceTime(1000), // debounce for 1 second
        switchMap((value) => this.search(value))
      )
      .subscribe((options) => {
        this.options = options;
      });
  }

  onInputChange(event: Event): void {
    const value = (event.target as HTMLInputElement).value;
    this.searchSubject.next(value);
  }

  search(value: string) {
    return this.http
      .get<string[]>('https://jsonplaceholder.typicode.com/users')
      .pipe(map((response) => response));
  }

  onScrollEnd(atEnd: boolean): void {
    console.log('Scrollbar is at the end');
  }
}

如您所见,指令已添加到组件

nz-autocomplete
。它是一个 ng-zorro 自动完成组件(https://ng.ant.design/components/auto-complete/en)。

您能帮我理解为什么它不能正常运行吗?我猜:

  • 因为 nz-autocomplete 可能无法真正滚动
  • nz-autocomplete 内部代码不允许指令?
  • 滚动指令代码错误。我是指令新手,只是在线复制了代码。

我决定不使用 ng-zorro 的 Select 的原因,其中直接内置了无限加载:

  • 我不喜欢当用户单击并清空输入字段时显示的输入
    NotFoundContent
    。如果没有输入值,则只关注输入并且不显示任何内容(ng-zorro 的自动完成是如何工作的)。我只想在没有实际结果时才显示它。

enter image description here

  • 我希望当前选择/输入的文本保留在字段中。在 ng-zorro 的 Select 中,每当用户选择时,您无法删除之前输入的文本。在下图中,我想清除“apple”文本,但它不允许我这样做,因为它变成了
    placeholder now

enter image description here

如果您能帮助我根据我的喜好调整 ng-zorro 的 Select(如果更容易的话),我也将不胜感激。谢谢你。

Stackblitz 链接到我的存储库:https://stackblitz.com/edit/angular-awrmdb-4dhtrr

angular antd ng-zorro-antd
1个回答
0
投票

正如您所说,最好选择

nz-select
,因为这种方法的错误数量最少,并且只需模拟自动完成即可。

请在下面找到用于实现nz select的serversearch和搜索框的属性,我也使用

nzFocus
来实现在搜索框上显示所选项目,请随意调整为您喜欢的!

我使用下面的 CSS 来隐藏占位符(如文本)!

::ng-deep .ant-select-single.ant-select-open .ant-select-selection-item {
    display: none !important;
}

HTML

<nz-select
    #select
    nzShowSearch
    nzServerSearch
    nzPlaceHolder="select something" 
    style="width:100%;"
    nzPlaceHolder=""
    [(ngModel)]="selected"
    (nzOnSearch)="searchSubject.next($event)"
    (nzFocus)="focus()">
    <nz-option
      *ngFor="let option of options"
      [nzLabel]="option.name"
      [nzValue]="option.name"
    ></nz-option>
  </nz-select>

TS

  focus() {
    if (this.selected) {
      setTimeout(() => {
        const input = this.select?.nativeElement?.querySelector('input');
        input.value = this.selected;
      });
    }
  }

完整代码:

import {
  Directive,
  ElementRef,
  EventEmitter,
  Output,
  HostListener,
  ViewChild,
} from '@angular/core';
import { debounceTime } from 'rxjs/operators';

@Directive({
  selector: '[scrollEnd]',
})
export class ScrollEndDirective {
  @Output() scrolledToEnd = new EventEmitter<boolean>();

  constructor(private el: ElementRef) {
    console.log('constructor logger'); // <- this is logging
  }

  @HostListener('scroll', ['$event'])
  onScroll(event: Event): void {
    const element = this.el.nativeElement as HTMLElement;
    console.log(element); // <-- this is not even logging

    if (element.scrollHeight - element.scrollTop === element.clientHeight) {
      this.scrolledToEnd.emit(true);
    } else {
      this.scrolledToEnd.emit(false);
    }
  }
}

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map, switchMap } from 'rxjs/operators';
import { Subject } from 'rxjs';

@Component({
  selector: 'nz-demo-auto-complete-options',
  template: `
    <div class="example-input">
      <nz-select
        #select
        nzShowSearch
        nzServerSearch
        nzPlaceHolder="select something" 
        style="width:100%;"
        nzPlaceHolder=""
        [(ngModel)]="selected"
        (nzOnSearch)="searchSubject.next($event)"
        (nzFocus)="focus()">
        <nz-option
          *ngFor="let option of options"
          [nzLabel]="option.name"
          [nzValue]="option.name"
        ></nz-option>
      </nz-select>

      {{selected  | json}}
      <!-- <nz-autocomplete #auto scrollEnd (scrolledToEnd)="onScrollEnd($event)">
        <nz-auto-option *ngFor="let option of options" [nzValue]="option.name">{{ option.name }}</nz-auto-option>
      </nz-autocomplete> -->
    </div>
  `,
  styles: [
    `
    ::ng-deep .ant-select-single.ant-select-open .ant-select-selection-item {
        display: none !important;
    }
  `,
  ],
})
export class NzDemoAutoCompleteOptionsComponent {
  @ViewChild('select', { read: ElementRef }) select!: ElementRef<any>;
  selected = null;
  isOpen = false;
  inputValue?: string;
  options: string[] = [];
  private searchSubject = new Subject<string>();

  constructor(private http: HttpClient) {
    this.searchSubject
      .pipe(
        debounceTime(250), // debounce for 1 second
        switchMap((value: any) => this.search(value))
      )
      .subscribe((options) => {
        this.options = options;
      });
  }

  focus() {
    if (this.selected) {
      setTimeout(() => {
        const input = this.select?.nativeElement?.querySelector('input');
        input.value = this.selected;
      });
    }
  }

  search(value: string) {
    return this.http
      .get<string[]>('https://jsonplaceholder.typicode.com/users')
      .pipe(
        map((response) =>
          response.filter((item: any) =>
            item.name.toLowerCase().includes(value.toLowerCase())
          )
        )
      );
  }
}

Stackblitz 演示

© www.soinside.com 2019 - 2024. All rights reserved.