首页 > 解决方案 > Provider 在 Angular 中初始化后无法访问类变量

问题描述

我创建了以下项目https://stackblitz.com/edit/angular-agzqbf您可以在控制台中看到变量xundefined从头开始的,即使在初始化变量之后ngOnInit

在此处输入图像描述

打印出值的函数xformat()继承自父类的函数,每次在input带有日历的字段中选择日期时调用它。但它总是undefined即使在通过按钮调用更改其值之后changeValue()

这是供应商的正常行为吗?或者我怎样才能确保format()函数可以访问变量类?

app.component.html

<form class="form-inline">
  <div class="form-group">
    <div class="input-group">
      <input class="form-control" placeholder="yyyy-mm-dd"
             (focus)="d.open()" name="dp" [(ngModel)]="model" ngbDatepicker #d="ngbDatepicker">
      <div class="input-group-append">
        <button class="btn btn-outline-secondary calendar" (click)="d.toggle()" type="button"></button>
      </div>
    </div>
  </div>
</form>


<button (click)="changeValue()"> Change X value</button>

app.component.ts

import { Component, OnInit } from '@angular/core';
import { NgbDateParserFormatter, NgbDateStruct } from "@ng-bootstrap/ng-bootstrap";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: []
})
export class AppComponent extends NgbDateParserFormatter implements OnInit {
  title = 'test-project';

  x: number;
  model;

  constructor() {
    super();
  }

  ngOnInit() {
    this.x = 9;
  }

  changeValue() {
    this.x = 5;
    console.log('x changed', this.x);
  }

  private padNumber(value: number) {
    if (this.isNumber(value)) {
        return `0${value}`.slice(-2);
    } else {
        return "";
    }
  }

  private isNumber(value: any): boolean {
    return !isNaN(this.toInteger(value));
  }

  private toInteger(value: any): number {
    return parseInt(`${value}`, 10);
  }

  parse(value: string): NgbDateStruct {
    if (value) {
      const dateParts = value.trim().split('/');
      if (dateParts.length === 1 && this.isNumber(dateParts[0])) {
        return {year: this.toInteger(dateParts[0]), month: null, day: null};
      } else if (dateParts.length === 2 && this.isNumber(dateParts[0]) && this.isNumber(dateParts[1])) {
        return {year: this.toInteger(dateParts[1]), month: this.toInteger(dateParts[0]), day: null};
      } else if (dateParts.length === 3 && this.isNumber(dateParts[0]) && this.isNumber(dateParts[1]) && this.isNumber(dateParts[2])) {
        return {year: this.toInteger(dateParts[2]), month: this.toInteger(dateParts[1]), day: this.toInteger(dateParts[0])};
      }
    }   
    return null;
  }

  format(date: NgbDateStruct): string {
    console.log('x value', this.x);
    let stringDate: string = ""; 
    if(date) {
      stringDate += this.isNumber(date.year) ? date.year + "/" : "";
      stringDate += this.isNumber(date.month) ? this.padNumber(date.month) + "/" : "";
      stringDate += this.isNumber(date.day) ? this.padNumber(date.day) : "";
    } 
    return stringDate;
  }
}

PS:parse()format()函数都是从父类继承来设置正确格式的输入字段选择日期后

标签: angularangular-componentsng-bootstrapangular-providers

解决方案


让我们看看 NgModule 的描述

providers: [{ provide: NgbDateParserFormatter, useClass: AppComponent}] 

这个字符串意味着当某些东西试图注入NgbDateParserFormatterangular 时会创建AppComponent并传递它。要实现您要实现的目标,请将提供程序部分添加到应用程序组件,useExisting: AppComponent如下所示:

@Component({
...
providers: [{ provide: NgbDateParserFormatter, useExisting: AppComponent }]
})
export class AppComponent{
...

推荐阅读