html - Angular:错误类型错误:无法读取 null 的属性“choice_set”,而数据显示正确
问题描述
我希望你一切都好。
我正在尝试通过从 API 访问数据来在 Angular 中实现 FormsBuilder。数据通过@Input() 下推到其子组件。
但是,数据被下推,提供并成功显示,但是当来自 ngOnChangess 的第一次尝试尝试接收数据时,我仍然收到此错误。
ERROR TypeError: Cannot read property 'choice_set' of null
at StyleTypeQuestionComponent.setFormValues (style-type-question.component.ts:34)
at StyleTypeQuestionComponent.ngOnChanges (style-type-question.component.ts:26)
at StyleTypeQuestionComponent.rememberChangeHistoryAndInvokeOnChangesHook (core.js:1471)
at callHook (core.js:2490)
at callHooks (core.js:2457)
at executeInitAndCheckHooks (core.js:2408)
at refreshView (core.js:9207)
at refreshEmbeddedViews (core.js:10312)
at refreshView (core.js:9216)
at refreshComponent (core.js:10358)
数据通过数据服务提供,并通过异步管道从其父组件订阅,并且如上所述通过属性绑定下推。
我尝试使用 ? 我的模板中的运算符并尝试在子组件上设置超时。我也尝试通过默认值初始化数据。这对我来说仍然没有任何意义,因为数据已经可以通过他的父组件获得,并通过 *ngIf 指令进行检查。
我希望我能提供尽可能多的信息。
我猜在 ngChanges 的前几秒有一个初始化问题。
父组件
import { Component, Input, OnChanges, OnInit } from '@angular/core';
import { Question } from '../shared/models/question';
import { QuestionStoreService } from '../shared/question-store.service';
import { Observable } from 'rxjs';
@Component({
selector: 'pc-style-type-detection',
templateUrl: './style-type-detection.component.html',
styleUrls: ['./style-type-detection.component.css'],
})
export class StyleTypeDetectionComponent implements OnInit, OnChanges {
question$: Observable<Question>;
@Input() question_Input: Question;
question_index: number = 1;
constructor(private qs: QuestionStoreService) {}
ngOnInit(): void {
this.question$ = this.qs.getSingle(1);
}
ngOnChanges(): void {}
updateBook(question: Question): void {
console.log(question);
}
}
父模板
<pc-style-type-question
*ngIf="question$"
(submitQuestion)="updateBook($event)"
[question]="question$ | async"
></pc-style-type-question>
子组件
import {
Component,
EventEmitter,
Input,
OnChanges,
OnInit,
Output,
} from '@angular/core';
import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
import { Choice, Question } from '../shared/models/question';
@Component({
selector: 'pc-style-type-question',
templateUrl: './style-type-question.component.html',
styleUrls: ['./style-type-question.component.css']
})
export class StyleTypeQuestionComponent implements OnInit, OnChanges {
questionForm: FormGroup;
@Input() question: Question;
@Output() submitQuestion = new EventEmitter<Question>();
constructor(private fb: FormBuilder) {}
ngOnChanges(): void {
this.initForm();
this.setFormValues(this.question);
}
ngOnInit(): void {
this.initForm();
}
private setFormValues = (question: Question) => {
this.questionForm.patchValue(question.choice_set);
this.questionForm.setControl(
'choice_set',
this.buildChoiceSetArray(question.choice_set)
);
};
initForm = () => {
if (this.questionForm) {
return;
}
this.questionForm = this.fb.group({
choice_set: this.buildChoiceSetArray([
{
choice_text: '',
choice_value: false,
},
]),
});
};
get choiceSet(): FormArray {
return this.questionForm.get('choice_set') as FormArray;
}
private buildChoiceSetArray = (values: Choice[]): FormArray => {
if (values) {
return this.fb.array(
values.map((choice) => {
return this.fb.control(choice.choice_value);
})
);
}
return this.fb.array(
this.question.choice_set.map((choices) =>
this.fb.control(choices.choice_value)
)
);
};
submitForm() {}
}
子模板
<form class="ui form" [formGroup]="questionForm" (ngSubmit)="submitForm()">
<div
formArrayName="choice_set"
*ngFor="let choiceset of choiceSet?.controls; index as i"
>
<div>
<input type="checkbox" [formControl]="choiceset" />
<label>
{{ question.choice_set[i].choice_text }}
</label>
</div>
</div>
</form>
提前感谢您,并祝您周末愉快。
解决方案
您没有使用ngOnChanges
正确的方法,无论值是什么,每次您的输入更改时都会触发它,这意味着您需要检查该值是否是您期望的值SimpleChanges
。
ngOnChanges(changes: SimpleChanges) {
if(changes.question.currentValue) {
this.initForm();
this.setFormValues(this.question);
}
}
推荐阅读
- django - AWS CodePipeline - 部署到 Elastic Beanstalk 需要 18 小时。我如何取消它?
- javascript - 如何在 Express 中将价值从一条路线传递到另一条路线?
- android - 如何在 Android 的图层列表中调整位图图像的大小?
- java - Spring ResponseBody 的 ObjectMapper 和 Jackson 的 ObjectMapper 的区别?
- javascript - 使用 jquery 引导表单验证
- bash - 如何将多字串分配到数组中
- android - USB 摄像头通过 RTMP 实时流式传输在 android 中存在问题
- sql - Oracle 删除姓名/姓氏/电话和地址
- android - 在android studio中更改根项目名称
- amazon-web-services - 如果我们使用 AWS RDS,是否需要进行数据库备份?