理解 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 {}
我的问题可能重复,请见谅。 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 {}