简体   繁体   English

angular 5-当通过@Input将函数从组件传递到指令时,“ this”是指指令而不是Component

[英]angular 5 - “this” refers to Directive instead of Component, when passing a function from component to directive through @Input

I'm trying to make an autocomplete directive with angular. 我正在尝试使用angular创建一个自动完成指令。

I've made a small demo for this problem: 我为这个问题做了一个小演示:

 import { Component, NgModule, VERSION, Directive, Injectable, Input } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; @Directive({ selector: "[autocompleter]", host: { "(keyup)": "onKey($event)" } }) export class AutocompleterDirective{ @Input("autocompleter") getFilteredData: (term: string) => Promise<string[]>; private term = ""; public onKey(event: any) { this.term = event.target.value; this.search(); } private search() { this.getFilteredData(this.term) .then((res) => { //do something to show the results list }); } } @Injectable() export class DataService { searchStrings: string[]; getStringsFilteredByTerm(term: string) { //do some filters on searchStrings... return this.searchStrings; } } @Component({ selector: 'my-app', template: ` <div> <input type="text" [autocompleter]="getFilteredData" autocomplete="off" /> </div> `, }) export class AppComponent{ constructor(private dataService: DataService) { } private getFilteredData(term: string){ let filteredStrings = this.dataService.getStringsFilteredByTerm(term); //"this" refers to the AutocompleterDirective instead of AppComponent var promise = new Promise((resolve, reject) => { resolve(filteredStrings); }); return promise; } } @NgModule({ imports: [BrowserModule], declarations: [AppComponent, AutocompleterDirective], providers: [DataService], bootstrap: [AppComponent] }) export class AppModule {} 

the problem is that in the "getFilteredData" function in "AppComponent", "this" refers to "AutocompleterDirective" instead of referring to "AppComponent", and I get this error: 问题是在“ AppComponent”的“ getFilteredData”函数中,“ this”是指“ AutocompleterDirective”,而不是“ AppComponent”,并且出现此错误:

Cannot read property 'getStringsFilteredByTerm' of undefined 无法读取未定义的属性“ getStringsFilteredByTerm”

I need to get the data from "dataService" which injected to "AppComponent". 我需要从注入到“ AppComponent”的“ dataService”中获取数据。

Is there any way to solve this? 有什么办法解决这个问题?

you're losing the scope, you can define your function using arrow function syntax to keep the correct scope, like so: 如果失去作用域,则可以使用箭头函数语法定义函数,以保持正确的作用域,如下所示:

  getFilteredData = (term: string) => {
    let filteredStrings = this.dataService.getStringsFilteredByTerm(term); //"this" refers to the AutocompleterDirective instead of AppComponent
    var promise = new Promise((resolve, reject) => {
      resolve(filteredStrings);
    });
    return promise;
  }

Side note: notice I didn't declare it as private, your prod builds will fail if you actually define that function as private and then try to pass it in template, though the dev server will work just fine. 旁注:请注意,我没有将其声明为私有,但是如果您实际上将该函数定义为私有,然后尝试在模板中传递它,则您的prod构建将失败,尽管开发服务器可以正常工作。

In your component, for the function you are passing, add .bind(this) onto it, see if that works: 在您的组件中,对于要传递的功能,在其上添加.bind(this),看看是否可行:

const theFunc = () => {
    // blah
}.bind(this)

And pass that through. 并通过。

If that fails, try the same but using ES5 function syntax. 如果失败,请尝试相同的操作,但使用ES5函数语法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM