【问题标题】:Form Builder - Cannot read property 'get' of undefined, issue with validators表单生成器 - 无法读取未定义的属性“获取”,验证器存在问题
【发布时间】:2019-03-27 16:26:01
【问题描述】:

我的 Angular 6 项目中有一个 Form Builder 表单,但我遇到了验证器问题。

我想我知道问题出在哪里,但不知道如何解决。 我有一个自定义验证器(不是真正的自定义,我使用 min() 和 max() 以及自定义变量进行检查)

并且可能在这些值之前初始化表单。

表单在构造函数之前声明(我尝试将其移入构造并移入ngOnInit,结果相同)

myForm = this.fb.group({
        title: [""],
        date: [""],
        max_score: [, [Validators.required, Validators.max(6), Validators.min(1)]],
        min_score: [, [Validators.required, Validators.max(6), Validators.min(1)]]
});

constructor(private fb: FormBuilder) {}

像这样一切正常,即使是验证器。 max_scoremin_score 是 2 个下拉菜单,您可以在其中选择一个数字。

我想要实现的是:

max_score: [, [Validators.required, Validators.max(6), Validators.min(this.myForm.get("min_points").value)]],
min_score: [, [Validators.required, Validators.max(this.myForm.get("max_score").value), Validators.min(1)]]

所以基本上max_score不能低于min_scoremin_score不能高于max_score

但这给了我错误:

TypeError: Cannot read property 'get' of undefined

所以我猜这是因为在初始化表单构建器时无法访问this.myForm.get("max_score").value

我该如何解决这个问题?这些值在我的表单中是可选的,因此它们在开始时没有值是正确的,我只想进行检查以避免选择高于 max_value 的 min_value

我什至尝试将 this.myForm.get.... 放在一个函数中:

getMaxPoints(): number {
        if (this.myForm.get("max_score").value) {
            return this.myForm.get("max_score").value;
        } else return null;
    }

然后

 min_score: [, [Validators.required, Validators.max(this.getMaxPoints()), Validators.min(1)]]

但我得到了同样的错误!

解决此问题的方法是什么?

【问题讨论】:

  • 这不是max_score 而不是this.myForm.get("max_points").value) 同样适用于min_points
  • 对不起,这只是 stackoverflow 上的一个错字,在我的代码中,它到处都是 max_score!所以不是这样的

标签: javascript angular forms angular6 formbuilder


【解决方案1】:

创建表单时,您将值传递给验证器数组,这些值仅在创建时传递。

所以如果你使用像

这样的表达式
Validators.max(this.myForm.get("max_points").value)

您正在创建表单期间进行评估。所以myForm 变量仍然是未定义的。

尝试使用一些变量而不是像这样访问myForm 属性:

minVal: number = 5;
maxVal: number = 5;

max_score: [, [Validators.required, Validators.max(6), Validators.min(minVal)]],
min_score: [, [Validators.required, Validators.max(maxVal), Validators.min(1)]]

要验证从表单中获取某些参数的数据,您应该使用来自this.fb.group() 的额外参数

你可以试试这样的:

myForm = this.fb.group({
        title: [""],
        date: [""],
        max_score: [, [Validators.required]],
        min_score: [, [Validators.required]]
},
{
       // THIS IS EXTRA!!!!!
       validator: [customValidator()]
});

这是customValidator的一个例子:

export function customValidator() {
  return (group: FormGroup) => {
    const minScore = group.controls['min_score'],
      maxScore = group.controls['max_core'],
      minPoints = group.controls['min_points'];

    if (/** some condition **/) {
      return minPoints.setErrors({'notMatching': true});
    } else {
      return minPoints.setErrors(null);
    }
  };
}

请注意,在 customValidator 中,您正在访问 myForm 数据,动态访问其控件。

然后在您的模板中,您需要显示错误,具体取决于

<div *ngIf="f.min_points.errors && f.min_points.errors.notMatching">NOT VALID</div>

我不记得notMatching 错误是否可用,但您可以使用

打印所有可用错误
<pre>{{ f.min_points.errors | json }</pre>

f 是一个方便的 getter 方法,如下所示:

 get f() {
    return this.myForm.controls;
  }

【讨论】:

  • 是的,我明白了,这就是我尝试使用函数的原因:getMaxScore(): number { if (this.myForm.get("max_score").value) { return this.detailsForm .get("max_score").value; } 否则返回 6;所以如果 myForm 仍然未定义,它将返回一个数字“6”,因此验证器将有一个值,但它不起作用,我得到同样的错误,这次是在我创建的函数的行上,所以我怎么能有一个验证器,它不允许我的 min_score 高于我的 max_score,反之亦然
  • 是的,但是在你的函数中你访问的仍然是 myForm,所以它仍然是未定义的 :)
  • 是的,我知道,但那我该如何解决呢?最终我需要访问 myForm 中的这些值来验证值并检查 min_score
  • 好的,如果我像你一样做,用 minVal 和 maxVal 初始化,然后我使用 myForm.get("max_score").valueChanges 并在 ngOnInit 上订阅它,所以当在那里做了一个改变,我做了: maxVal = myForm.get("max_score").value
  • 让我们试试我的新解决方案
【解决方案2】:

应该是:

public myForm:FormGroup; // you should do this
constructor(private fb: FormBuilder) {
     this.myForm = this.fb.group({
        title: [''],
        date: [''],
        max_score: ['', [Validators.required, Validators.max(6), Validators.min(1)]],
        min_score: ['', [Validators.required, Validators.max(6), Validators.min(1)]]
     });
}

并访问它:

this.myForm.get("max_score").value

或:

this.myForm.controls["max_score"].value

【讨论】:

  • 我看不到它解决了 OP 的问题以确保 min 是
  • 您的解决方案中唯一改变的是您将 Formbuilder 的初始化移到构造函数中!没有改变任何东西,我尝试在构造函数和 NgOnInit 中移动它,同样的错误
  • @AJ989 你得到未定义的错误,所以你做错了表单定义你可以试试这个然后说它有没有帮助,也检查this
  • @fatemefazli 我确实尝试过,我声明了 myForm 变量,并在构造函数中对其进行了初始化,然后我也尝试使用其他版本 this.myForm.controls[...] 但我得到了同样的错误 TypeError: Cannot read property 'controls' of undefined
  • And ofc 在表单的声明中,验证器所在的位置,我没有离开:Validators.max(6),当然,正如我在我的 OP 中所写,我把this.myForm.get("max_score").value 那里,它给出了错误
【解决方案3】:

您可以在 html 中添加 (keyup)="checkMinMax()" 的最小值和最大值。在 checkMinMax 函数中,您可以检查 this.myForm.get("max_score").valuethis.myForm.get("min_score").value 的内容,或者显示一条带有 *ngIf 的消息,就像您在评论中提到的那样,或者如果用户的输入超过它,则强制最小值或最大值与另一个相同. ( 或两者 )。

此外,通过这样做,您可以使用所需的验证器。

【讨论】:

    【解决方案4】:

    我相信我有解决这个问题的简单方法。这是一个时间问题。我通过将成员变量定义为静态来使其工作。我的代码如下:

    static numberOfVerses: number;
    ..
    form: FormGroup = new FormGroup({
        suraID: new FormControl('', Validators.required),
        bVerseID: new FormControl('', Validators.required),
        eVerseID: new FormControl('', Validators.required),
        translatorID1: new FormControl(''),
      },validate);
    
    // reference the static variable in the custom validation
    validate(control: AbstractControl): { [key: string]: boolean } | null {
    
        const suraID = control.get('suraID');
        const bVerseID = control.get('bVerseID');
        const eVerseID = control.get('eVerseID');
        const translatorID1 = control.get('translatorID1');
    
    
        if (suraID && bVerseID && eVerseID && QuranSearchComponent.numberOfVerses) {
          if (bVerseID.value > QuranSearchComponent.numberOfVerses || eVerseID.value > QuranSearchComponent.numberOfVerses) {
            return { 'invalid_verse_number': true };
          }
        }
    
        if (suraID && bVerseID && eVerseID && translatorID1 &&
            bVerseID.value > eVerseID.value) {
    
            return { 'invalid_verse_range': true };
        }
        return null;
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-25
      • 1970-01-01
      • 2018-06-02
      • 2016-09-22
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      相关资源
      最近更新 更多