首页 > 解决方案 > @ViewChild 注释的使用在我的代码中返回 undefined

问题描述

我有一个角度 2 UI。我在我的组件模板中定义了一个文本区域,并尝试使用 @ViewChild 注释获取对该文本区域的引用。但是它返回 undefined 。我知道原因,但不知道如何解决这个问题。问题出在

所以这是我在组件 html 中的文本区域

<textarea id="messageTxt" formControlName="message" rows="6" [placeholder]="'PLACEHOLDERS.MESSAGE' | translate" #messageTxt></textarea>

所以我从我的组件 ts 文件中粘贴部分代码,如下所示。messageTextArea 原来是未定义的。我想这是因为 ngOnInit 方法,我们正在等待创建表单,直到我们得到服务的响应。知道如何重写代码,以便在 messageTextArea 变量中获得正确的引用。

export class SmsTemplateFormComponent implements OnInit,AfterViewInit {

  @ViewChild('messageTxt') messageTextArea: ElementRef;

constructor(
    private fb: FormBuilder,
    private templatesService: TemplatesService,
    private configService: ConfigService,
    private accountService: AccountsService
  ) {}

ngAfterViewInit() {
    fromEvent(this.messageTextArea.nativeElement,'keyup').pipe(
      map( (e: KeyboardEvent) => (e.target as HTMLTextAreaElement).value),
      debounceTime(10),  
      distinctUntilChanged(),
      switchMap( (value) =>  this.templatesService.retrieveSmsSegmentCount(value)  )
     ).subscribe(
        response => {
          this.segmentCount = response.segmentCount;
        } 
     );
  }

 ngOnInit() {
    this.isFormLoading = true;
    this.accountService.get(this.account.id).subscribe(
        (value) => {
            this.account = value;
            this.isFormLoading = false;
            this.messagePrefix = value.messagePrefix;
            this.formGroup = this.fb.group(
                  {
                    defaultTemplate: [this.defaultInitialValue],
                    language: [null, Validators.required],
                    message: [ this.messagePrefix ? this.messagePrefix:'', [Validators.required]],
                    longUrl: ['']
                  },
                  {
                    validator: [
                                hasUrlTagValidator(TemplatesService.urlTag), 
                                messagePrefixSMSValidator(this.messagePrefix? this.messagePrefix: null, 'message')
                              ]
                  }
                );

              combineLatest(
                this.messageControl.valueChanges,
                this.urlControl.valueChanges
              ).subscribe(([message, url]) => {
                const { html, length } = this.templatesService.compileSmsTemplate(
                  message,
                  url ? this.placeholderUrl : ''
                );

                this.messageHtml = html;
                this.messageLength = length;
              });

              if (this.template) {
                this.formGroup.setValue({
                  defaultTemplate: this.template.defaultTemplate,
                  language: this.template.language,
                  message: this.template.text,
                  longUrl: this.template.longUrl
                });
              }

              this.urlControl.valueChanges.subscribe(() => {
                const messageValue: string = this.messageControl.value;
                if (!messageValue || !messageValue.includes(TemplatesService.urlTag)) {
                  this.messageControl.setValue(messageValue + TemplatesService.urlTag);
                }
              });

              this.templatesService.retrieveSmsSegmentCount(this.messageControl.value)
              .subscribe( response => {
                this.segmentCount = response.segmentCount;
                });
        }
    );
  }

}

标签: angularangular5

解决方案


在你的情况下你真的不需要fromEvent。您可以将keyup事件绑定到您的文本区域:

<textarea id="messageTxt" formControlName="message" rows="6" [placeholder]="'PLACEHOLDERS.MESSAGE' | translate" (keyup)="doStuff(messageTxt.value)" #messageTxt></textarea>

然后在您的组件中:

doStuff(value: string) {
  // do whatever with the value
}

推荐阅读