首页 > 解决方案 > 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>

提前感谢您,并祝您周末愉快。

标签: htmlangulartypescript

解决方案


您没有使用ngOnChanges正确的方法,无论值是什么,每次您的输入更改时都会触发它,这意味着您需要检查该值是否是您期望的值SimpleChanges

ngOnChanges(changes: SimpleChanges) {
    if(changes.question.currentValue) {
        this.initForm();
        this.setFormValues(this.question);
    }
}

推荐阅读