如何从指令行为中排除特殊情况?

Posted

技术标签:

【中文标题】如何从指令行为中排除特殊情况?【英文标题】:How to exclude a special case from a directive behavior? 【发布时间】:2020-04-03 22:11:08 【问题描述】:

我正在尝试修复在我的页面上搜索时遇到的错误。我有一个组件可以在我的所有设置中搜索,如下所示:

一切正常,搜索返回它应该返回的值,但是当我删除搜索条件时,我注意到条件的第一个字母仍然显示并且不会消失,即使搜索设置字段是空的,就像这样:

在代码检查了两个小时后,我可以看到代码中的问题所在,但我不知道如何解决。

这是我的组件的 html

<mat-form-field appearance="standard">
      <input matInput
             pageSearch
             placeholder="'searchSettings'|translate">
    </mat-form-field>

如您所见,我使用了一个名为 pageSearch 的指令,其定义如下,并包含一个方法 valueChange,该方法在每次释放键盘键时执行:

ngAfterViewInit() 
    const subscription = this.router.events
      .pipe(filter(e => e instanceof NavigationStart))
      .subscribe(event => 
          if (event) 
            this.pageSearchService.term.next('');
          
        
      );
    this.subscriptionsManager.add(subscription);
  

@HostListener('keyup')
  valueChange() 
    this.pageSearchService.term.next(
      this.elementRef.nativeElement.value
    );
  

该指令使用pageSearchService,定义如下:

@Injectable()
export class PageSearchService 
  /**
   * Current search term.
   */
  term: BehaviorSubject<string>;
  /**
   * Event to emit when visibility should change in the searchable.
   */
  searchableMatch: EventEmitter<any> = new EventEmitter<any>();

  constructor() 
    this.term = new BehaviorSubject('');
  

我有一个小小的想法,问题可能是它总是期待一个next() 值,当它为空时,它就不会运行,但它的最后一个值仍然被冻结在那里。

我曾尝试更改指令中的 valueChange 方法,但每次我最终都会关闭对 BehaviorSubject 的订阅。这些是我尝试过的事情:

    添加条件检查字符串是否为空且不调用BehaviorSubject
valueChange() 
    if (this.elementRef.nativeElement.value !== '') 
      this.pageSearchService.term.next(
        this.elementRef.nativeElement.value
      );
    
  

没用,我也试过退订再订阅,还是没用

valueChange() 
    if (this.elementRef.nativeElement.value !== '') 
      this.pageSearchService.term.next(
        this.elementRef.nativeElement.value
      );
     else 
      this.pageSearchService.term.unsubscribe();
      this.pageSearchService.term._subscribe(this.elementRef.nativeElement.value);
    
  

它给了我这个错误:

所以现在我不知道还能做什么。在给定字符串'' 的情况下,我如何要求指令不要以某种方式表现?

searchableMatchEventEmitter 被其他 3 个指令使用,如下:

SearchNoResultsDirective:

export class SearchNoResultsDirective implements AfterViewInit, OnDestroy 
  @Input('searchNoResults') sectionsId: string[];
  subscriptionsManager: Subscription = new Subscription();
  visibility: 
    term: string,
    visible: boolean
   = 
    term: '',
    visible: true
  ;

  constructor(private elementRef: ElementRef,
              private renderer: Renderer2,
              private pageSearchService: PageSearchService) 
  

.
.
.

  ngAfterViewInit() 
    const subscription = this.pageSearchService.searchableMatch.subscribe(match => 
      if (this.sectionsId.indexOf(match.sectionId) >= 0 ) 
        this.update(
          term: match.term,
          visible: match.visible
        );
      
    );
    this.subscriptionsManager.add(subscription);
  

SearchableSectionDirective:

export class SearchableSectionDirective extends BaseClass implements AfterViewInit 
  @Input('searchableSection') sectionId: string;

.
.
.

  ngAfterViewInit() 
    const subscription = this.pageSearchService.searchableMatch.subscribe(match => 
      if (match.sectionId === this.sectionId) 
        this.update(
          term: match.term,
          visible: match.visible
        );
      
    );
    this.subscriptionsManager.add(subscription);
  

还有 SearchableDirective:

export class SearchableDirective implements AfterViewInit, OnDestroy 
  @Input('searchable') sectionId: string;
  @Input() highlightColor = '#FFF176';
  match: EventEmitter<any> = new EventEmitter<any>();
  subscriptionsManager: Subscription = new Subscription();
  originalText: string;

  ngAfterViewInit() 
    this.originalText = this.elementRef.nativeElement.innerText;
    this.subscriptionsManager.add(
      this.pageSearchService.term.subscribe(term => this.checkIfMatch(term))
    );
  

  checkIfMatch(val: string) 
    let match = false;
    let clean = false;
    if (val) 
      const startInd = this.originalText.toLowerCase().indexOf(val.trim().toLowerCase());
      if (startInd > -1) 
        match = true;
        const startText = this.render.createText(this.originalText.slice(0, startInd));
        const matchText = this.render.createText(this.originalText.slice(startInd, startInd + val.trim().length));
        const endText = this.render.createText(this.originalText.slice(startInd + val.trim().length, this.originalText.length));

        const matchSpan = this.render.createElement('span');
        this.render.appendChild(
          matchSpan,
          matchText
        );
        this.render.setStyle(
          matchSpan,
          'background',
          this.highlightColor
        );

        this.elementRef.nativeElement.innerHTML = '';

        this.render.appendChild(
          this.elementRef.nativeElement,
          startText
        );
        this.render.appendChild(
          this.elementRef.nativeElement,
          matchSpan
        );
        this.render.appendChild(
          this.elementRef.nativeElement,
          endText
        );
       else 
        clean = true;
      
     else if (this.originalText) 
      clean = true;
    

    **if (clean) 
      // this is how the solution looks
      this.elementRef.nativeElement.innerHTML = this.originalText;
    **

    if (this.sectionId) 
      this.pageSearchService.searchableMatch.emit(
        sectionId: this.sectionId,
        term: val,
        visible: match
      );

      this.match.emit(
        term: val,
        visible: match
      );
    
  

我正在查看这 3 个指令,看看是否找到了问题。

【问题讨论】:

尝试监听事件document:keypress而不是keyup @NimittShah 我已经试过了,它没有用,实际上它破坏了搜索逻辑,现在我输入时它有延迟 如果您创建stackblitz.com 应用程序会很有帮助。 @NimittShah 我目前在一个私人项目工作。恐怕我不能透露比我已经拥有的更多的信息,因为我的 PO 不会批准。对不起:( searchableMatch 是否控制“阿凡达”中“A”的突出显示? searchableMatch 什么时候发出值? 【参考方案1】:

我认为唯一的问题是您放置逻辑的功能。 我想你只需要添加checkIfMatch

checkIfMatch(val: string) 

    let match = false;
    let clean = false;
    if (val) 

       //func logic

      else 
        // you need to add else block to the function
        this.elementRef.nativeElement.innerHTML = this.originalText;

     



【讨论】:

我现在试过了,还是不行,最后一个字母还是高亮。我相信我应该重置具有样式的渲染对象,我正在寻找如何做到这一点。还是非常感谢 @DairelysGarcíaRivas 请确保您对valueChange()没有任何条件 `valueChange()` 应该只做this.pageSearchService.term.next( this.elementRef.nativeElement.value); 这个指令没有valueChange()方法 我的意思是 pageSearch 指令

以上是关于如何从指令行为中排除特殊情况?的主要内容,如果未能解决你的问题,请参考以下文章

如何修改 Range 函数中边界值的包含/排除行为?

在某些特殊情况下,Win32 ShowWindow api 在 Windows 7 SP1 上的行为是不是不同?

如何从 gprof 中排除某个函数?

如何更改 C# Record 构造函数的行为

在 UICollectionView 中使用 reloadData 时如何从重新加载中排除标头

如何覆盖NullReferenceException行为以获得更好的信息性错误?