理解 Angular 中的界面和 FormGroup 问题

Problem in understanding Interface and FormGroup issue in Angular

我的问题可能重复,请见谅。 SO 中有很多相同问题的可用解决方案,但不幸的是我无法从技术角度理解这一点。

问题 1

src/app/models/dataModel.ts:2:5
2     id: number;
      ~~
The expected type comes from property 'id' which is declared here on type 'DataModel'


Error: src/app/models/dataModel.ts:2:5 - error TS2564: Property 'id' has no initializer and is not definitely assigned in the constructor.

2     id: number; 

我的dataModal.ts

export class DataModel {
    id: number;
    name?: string;
    gender?: string;
    age?: number;
    address?: string;
    city?: string;
    country?: string;
    status?: string;
    date?: Date;
}

案例-details.component.ts

export class CasesDetailsComponent implements OnInit {
  isLoadingResult = true;
  cases: DataModel = { id: null || undefined, name: '', gender: '', age: null || undefined, address: '', city: '' };

。 对于问题 1,每当我 ? 可选运算符时,问题就消失了,app 运行 顺利..我想明白,使用 的目的是什么? 为什么?

问题2

Error: src/app/component/add-case/add-case.component.ts:22:3 - error TS2564: Property 'formGroup' has no initializer and is not definitely assigned in the constructor.

22   formGroup: FormGroup;
     ~~~~~~~~~

正在尝试添加表单数据,因此在 add-case.component.ts

中进行如下初始化
export class AddCaseComponent implements OnInit {
  isLoadingResult = true;

  formGroup: FormGroup;
  id = null;
  name = '';
  age = null;
  status = '';
  gender = '';
  genderList = ['Male', 'Female',];
  statusList = [ 'Positive', 'Negative'];
  address = '';
  city = '';
  country = '';


  constructor(private router: Router, private api: ApiService, private formBuilder: FormBuilder) { }

  ngOnInit(): void {
    this.formGroup = this.formBuilder.group({
      name: [null, Validators.required],
      age: [null, Validators.required],
      status: [null, Validators.required],
      gender: [null, Validators.required],
      address: [null, Validators.required],
      city: [null, Validators.required],
      country: [null, Validators.required]
    });
  }



saveRecord(): void {
    this.isLoadingResult = true;
    this.api.addNewCaseDetails(this.formGroup.value).subscribe((response: any) => {
// other stuffs
}

}

package.json

"dependencies": {
    "@angular/animations": "~11.2.8",
    "@angular/cdk": "^11.2.8",
    "@angular/common": "~11.2.8",
    "@angular/compiler": "~11.2.8",
    "@angular/core": "~11.2.8",
    "@angular/forms": "~11.2.8",
    "@angular/material": "^11.2.8",
    "@angular/platform-browser": "~11.2.8",
    "@angular/platform-browser-dynamic": "~11.2.8",
    "@angular/router": "~11.2.8",

tsconfig.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2015",
    "module": "es2020",
    "lib": [
      "es2018",
      "dom"
    ]
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true,
    "strictPropertyInitialization": false
  }
}

有人可以帮我解决这个问题吗?

您遇到的问题是您正在定义 class 但没有初始化属性(在构造函数中或直接在定义它们时)。由于 Typescript 向您显示此消息,我假设您处于严格模式,这就是您收到此消息的原因。

回答你的第一个问题:? in id?:表示属性是可选的,她不一定要有值,可以为null。另一种解决方案是使用 id 参数定义构造函数: constructor(id: number){this.id = id;}

对于你的第二个问题,你应该尝试在你的构造函数体中移动你的表单初始化:

constructor(private router: Router, private api: ApiService, private formBuilder: FormBuilder) { 
  this.formGroup = this.formBuilder.group({
      name: [null, Validators.required],
      age: [null, Validators.required],
      status: [null, Validators.required],
      gender: [null, Validators.required],
      address: [null, Validators.required],
      city: [null, Validators.required],
      country: [null, Validators.required]
    });
}

至于为什么这是最佳实践,我目前没有答案,但我会寻找答案。

编辑:我看了一下,发现了这个:link

Typescript 需要确保未定义为可选的 属性 具有值(以避免 'undefined' 和运行时的技术问题)。似乎不是将您的 formGroup 初始化移动到您的构造函数,您也可以这样声明它:

myFormGroup!: FormGroup  // see the ! mark, it means that the property will be initialized in an other place that the constructor.

constructor(...) {}

ngOnInit() {
   this.myFormGroup = this.fb.formGroup({...});
}

学习者,可以加一些getter和setter来改变class的值吗?同样,我建议您使用界面来创建模型并对其进行处理

问题1我没有直接回答

对于问题 2,我会尝试从 ngOnInit() 函数外部设置。

export class AddCaseComponent implements OnInit {
  isLoadingResult = true;

  id = null;
  name = '';
  age = null;
  status = '';
  gender = '';
  genderList = ['Male', 'Female', 'Transgender'];
  statusList = ['Recoverd', 'Positive', 'Negative', 'Under treatment', 'Dead'];
  address = '';
  city = '';
  country = '';
  matcher = new MyErrorStateMatcher();

  formGroup = this.formBuilder.group({
      name: [null, Validators.required],
      age: [null, Validators.required],
      status: [null, Validators.required],
      gender: [null, Validators.required],
      address: [null, Validators.required],
      city: [null, Validators.required],
      country: [null, Validators.required]
      }};

  constructor(private router: Router, private api: ApiService, private 
              formBuilder: FormBuilder) { }

  ngOnInit(): void {}