How do I enable (onSelect) event handler to run first and prevent (onBlur) event from running as well using PrimeNG autocomplete

huangapple go评论78阅读模式
英文:

How do I enable (onSelect) event handler to run first and prevent (onBlur) event from running as well using PrimeNG autocomplete

问题

以下是翻译好的部分:

我这里有一个情况,我正在寻求一些帮助。目前正在开发一个搜索自动完成功能,其中选项是从组件中的预定义列表显示的。现在,这是我的 p-autocomplete 标签的样子:

<p-autoComplete [(ngModel)]="skills" [suggestions]="filteredSkillSuggestions"
           id="skills" name="skills" #skillList="ngModel" 
           (completeMethod)="search($event)"
           [dropdown]="false" 
           [unique]="true"
           [multiple]="true"
           (keyup)=onEnterClickEvent($event)
           (onBlur)="onOutsideClick($event)"
           placeholder="例如:Java,Angular,Terraform" 
           class="w-full p-fluid" ></p-autoComplete>

现在,有一个情景我正在尝试应对。假设我是一个用户,在这个输入框中手动输入文本,但由于某种原因,我的文本不会提供任何搜索建议。最终,我希望在我离开 <p-autoComplete> 标签时能够将它包含在输入框中。这里有一个 `onBlur` 事件可以帮助实现这一点,所以我是这样处理它的:

onOutsideClick(event: KeyboardEvent){
    let tokenInput = event.target as any
    if (tokenInput.value){
        this.skills.push(tokenInput.value)
        tokenInput.value = ""
    }
}

这在某种程度上有效,但在使用搜索建议进行选择时,会在 `onSelect` 事件之前触发一个 `OnBlur` 事件。这反过来会运行上面的代码,并将用户正在输入的手动输入和从搜索建议中选择的内容都包含在输入列表中。有没有一种方法可以让 `onSelect` 先运行,并在 `onSelect` 运行时完全忽略 `onBlur`?欢迎任何其他解决方法。

我已经尝试了 [这个答案][1] 建议的 `setTimeout()` 方法。

  [1]: https://stackoverflow.com/questions/57125841/primeng-autocomplete-onblur-fires-before-onselect-how-to-get-non-matching-value
英文:

I have a situation here and I was looking for some help. Currently developing a search autocomplete feature where options are displayed from a predefined list in the component. Now, this is how my p-autocomplete tag looks like:

 <p-autoComplete [(ngModel)]="skills" [suggestions]="filteredSkillSuggestions"
           id="skills" name="skills" #skillList="ngModel" 
           (completeMethod)="search($event)"
           [dropdown]="false" 
           [unique]="true"
           [multiple]="true"
           (keyup)=onEnterClickEvent($event)
           (onBlur)="onOutsideClick($event)"
           placeholder="Eg. Java, Angular, Terraform" 
           class="w-full p-fluid" ></p-autoComplete>

Now, there's a scenario I am trying to cater for. Let's say I am a user manually inputting text in this input but for some reason, my text does not give out any search suggestions. Ultimately, I want to be able to include it in the input when I focus out of the <p-autoComplete> tag. There is an onBlur event that can help with that so this is how I handle it:

  onOutsideClick(event: KeyboardEvent){
    let tokenInput = event.target as any
    if (tokenInput.value){
      this.skills.push(tokenInput.value)
      tokenInput.value = &quot;&quot;
    }
  }

This works to an extent but noticed an issue along the line. When selecting from the search suggestions, it emits an OnBlur event before the onSelect event. This in turn, runs this code above and includes both the manual input the user was typing, and the selection from the search suggestions, into the input list. Is there a way I could be able to run onSelect first and totally ignoring onBlur when onSelect runs? Any other workaround is appreciated.

I have already tried setTimeout() as suggested by this answer

答案1

得分: 1

To achieve the desired behavior of listening to the blur event of the input field in the autocomplete component and applying a delay before executing logic, you can follow these steps:

  1. 在你的HTML文件中,为自动完成组件添加一个模板引用:
<h5>基本</h5>
<p-autoComplete
  [(ngModel)]="selectedCountry"
  [suggestions]="filteredCountries"
  (onSelect)="select($event)"
  (completeMethod)="filterCountry($event)"
  #autoRef   <!-- 模板引用 -->
  field="name"
  [minLength]="1"
></p-autoComplete>
  1. 在你的组件中导入 AfterViewInit,并使用 @ViewChild 读取自动完成组件:
import { AfterViewInit, ViewChild } from '@angular/core';
import { AutoComplete } from 'primeng/autocomplete';

export class YourComponent implements AfterViewInit {
  @ViewChild('autoRef') autoRef: AutoComplete;
  
  // 组件其他部分的代码
}
  1. 在你的组件中实现 AfterViewInit 接口:
export class YourComponent implements AfterViewInit {
  ngAfterViewInit(): void {
    this.catchBlurEvent();
  }

  // 组件其他部分的代码
}
  1. 在你的组件中创建 catchBlurEvent() 函数。这个函数监听自动完成组件中输入字段的失焦事件,使用 RxJS 的 delay() 添加延迟,并订阅该事件:
import { fromEvent } from 'rxjs';
import { delay } from 'rxjs/operators';

export class YourComponent implements AfterViewInit {
  ngAfterViewInit(): void {
    this.catchBlurEvent();
  }

  catchBlurEvent() {
    fromEvent(this.autoRef.inputEL.nativeElement, 'blur')
      .pipe(delay(100))
      .subscribe((event: FocusEvent) => {
        // 在这里执行你的逻辑
      });
  }

  // 组件其他部分的代码
}

catchBlurEvent() 函数中,使用 fromEvent 创建一个来自自动完成组件输入字段失焦事件的可观察对象。然后,应用 delay 操作符以引入100毫秒的延迟。最后,订阅处理事件并执行你的期望逻辑。

通过实施这些步骤,你可以监听自动完成输入字段的失焦事件,并在执行逻辑之前引入延迟,而无需在HTML模板中使用 (onBlur)

英文:

To achieve the desired behavior of listening to the blur event of the input field in the autocomplete component and applying a delay before executing logic, you can follow these steps:

  1. Add a template reference to the autocomplete component in your HTML file:
&lt;h5&gt;Basic&lt;/h5&gt;
&lt;p-autoComplete
  [(ngModel)]=&quot;selectedCountry&quot;
  [suggestions]=&quot;filteredCountries&quot;
  (onSelect)=&quot;select($event)&quot;
  (completeMethod)=&quot;filterCountry($event)&quot;
  #autoRef   &lt;!-- Template reference --&gt;
  field=&quot;name&quot;
  [minLength]=&quot;1&quot;
&gt;&lt;/p-autoComplete&gt;
  1. Import AfterViewInit in your component and read the autocomplete component using @viewChild:
import { AfterViewInit, ViewChild } from &#39;@angular/core&#39;;
import { AutoComplete } from &#39;primeng/autocomplete&#39;;

export class YourComponent implements AfterViewInit {
  @ViewChild(&#39;autoRef&#39;) autoRef: AutoComplete;
  
  // Rest of your component code
}
  1. Implement the AfterViewInit interface in your component:
export class YourComponent implements AfterViewInit {
  ngAfterViewInit(): void {
    this.catchBlurEvent();
  }

  // Rest of your component code
}
  1. Create the catchBlurEvent() function in your component. This function listens to the blur event of the input field in the autocomplete component, adds a delay using RxJS delay(), and subscribes to the event:
import { fromEvent } from &#39;rxjs&#39;;
import { delay } from &#39;rxjs/operators&#39;;

export class YourComponent implements AfterViewInit {
  ngAfterViewInit(): void {
    this.catchBlurEvent();
  }

  catchBlurEvent() {
    fromEvent(this.autoRef.inputEL.nativeElement, &#39;blur&#39;)
      .pipe(delay(100))
      .subscribe((event: FocusEvent) =&gt; {
        // Your logic here
      });
  }

  // Rest of your component code
}

In the catchBlurEvent() function, fromEvent is used to create an observable from the blur event of the input field in the autocomplete component. The delay operator is then applied to introduce a delay of 100 milliseconds. Finally, the subscription handles the event and executes your desired logic.

By implementing these steps, you can listen to the blur event of the autocomplete input field and apply a delay before executing the logic, without the need to use (onBlur) in the HTML template.

huangapple
  • 本文由 发表于 2023年6月26日 19:28:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76556245.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定