如何从指令行为中排除特殊情况?
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);
它给了我这个错误:
所以现在我不知道还能做什么。在给定字符串''
的情况下,我如何要求指令不要以某种方式表现?
searchableMatch
EventEmitter 被其他 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 指令以上是关于如何从指令行为中排除特殊情况?的主要内容,如果未能解决你的问题,请参考以下文章
在某些特殊情况下,Win32 ShowWindow api 在 Windows 7 SP1 上的行为是不是不同?