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

时间:2019-12-10 16:52:10

标签: angular typescript angular-directive

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

Search settings component

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

Avatar string with A selected

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

这是我组件的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()值,而当它为null时,它只是不运行,但是它拥有的最后一个值仍然冻结在其中。

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

  1. 添加条件以检查字符串是否为空并且不调用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);
    }
  }

这给了我这个错误:

Error when unsubscribing

所以现在我不知道该怎么办。在给出字符串''的情况下,我该如何要求指令不执行某些操作?

searchableMatch EventEmitter由其他3个指令使用,如下所示:

SearchNoResults指令:

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);
  }
}

SearchableSection指令:

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);
  }
}

和Searchable指令:

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条指令,以查看是否找到问题。

1 个答案:

答案 0 :(得分:1)

我认为唯一的问题是放置逻辑的函数。 我认为您只需要添加Communications.makeWebRequest( "https://oauth2.googleapis.com/token", {"client_id"=>"934…alc.apps.googleusercontent.com", "client_secret"=>"mI…nY","code"=>"AH…KKw", "grant_type"=>"http://oauth.net/grant_type/device/1.0"}, {:method => Communications.HTTP_REQUEST_METHOD_POST}, method(:onTokenRefresh2GetData));

checkIfMatch