如何从指令行为中排除特殊情况?
How to exclude a special case from a directive behavior?
我正在尝试修复在我的页面上搜索时遇到的错误。我有一个组件可以在我的所有设置中搜索,如下所示:
一切正常,搜索返回了它应该返回的值,但是当我删除搜索条件时,我注意到条件的第一个字母仍然显示并且没有消失,即使搜索设置字段为空,就像这样:
查看代码两个小时后,我可以看到代码中的问题所在,但我不知道如何解决它。
这是我的组件 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 的订阅。这些是我尝试过的东西:
- 添加条件判断字符串是否为空不调用
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个指令使用,如下:
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);
}
}
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 个指令以查看是否找到了问题。
我认为唯一的问题是您放置逻辑的函数。
我认为您只需要添加 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;
}
}
我正在尝试修复在我的页面上搜索时遇到的错误。我有一个组件可以在我的所有设置中搜索,如下所示:
一切正常,搜索返回了它应该返回的值,但是当我删除搜索条件时,我注意到条件的第一个字母仍然显示并且没有消失,即使搜索设置字段为空,就像这样:
查看代码两个小时后,我可以看到代码中的问题所在,但我不知道如何解决它。
这是我的组件 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 的订阅。这些是我尝试过的东西:
- 添加条件判断字符串是否为空不调用
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个指令使用,如下:
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);
}
}
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 个指令以查看是否找到了问题。
我认为唯一的问题是您放置逻辑的函数。
我认为您只需要添加 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;
}
}