简体   繁体   English

以角度形式添加验证器

[英]Adding validators in angular forms

I am testing this html form: 我正在测试此html表单:

  <input #nhcInput type="text" class="form-control" name="nhc" id="field_nhc" [(ngModel)]="paciente.nhc" maxlength="38" pattern="[0-9]+"/> <div [hidden]="!(editForm.controls.nhc?.dirty && editForm.controls.nhc?.invalid)"> <small class="form-text text-danger" [hidden]="!editForm.controls.nhc?.errors?.maxlength" jhiTranslate="entity.validation.maxlength" translateValues="{ max: 38 }"> This field cannot be longer than 38 characters. </small> 

 TEH RESULT {{nhcInput.className}} //This line prints ng-valid/ dirty, touched correctly 

I have this in my component: 我的组件中有这个:

  paciente: Paciente = {nhc: '23423' } as Paciente; 

  it ('NHC cannot have more than 38 characters', async(() => { comp.paciente.nhc = 'rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr' ; console.log(fixture.nativeElement.querySelector('input[name="nhc"]').className); fixture.detectChanges(); expect(fixture.nativeElement.querySelector('input[name="nhc"]').className.includes('ng-invalid')).toEqual(true); })); 

Now I want to test the validity by checking the vaidator. 现在,我想通过检查验证程序来测试有效性。 The console.log prints out only form-control without the type of validator, since it is not finding it. console.log因为没有找到验证器,所以只打印出窗体控制,而没有验证器的类型。

I put a validator for this fild like this in my component: 我在组件中放置了一个用于此fild的验证器:

 @ViewChild('editForm') editForm: any; editform.controls["nhc"].setValidators([ Validators.maxLength(38)]); 

But this doesnt work. 但这不起作用。 Am I doing soemthing wrong here? 我在这里做错什么吗?

Thanks! 谢谢!

Your issue comes from the fact that you don't do things in order and don't rely on the framework to make your tests. 您的问题来自于这样一个事实,即您没有按顺序进行操作,也不依赖框架进行测试。

I made a sandbox with a working test, feel free to look at it. 我制作了一个具有测试功能的沙盒 ,随时查看。 Now for the explanation : 现在进行解释:

Let's start with the component : 让我们从组件开始:

@Component({
  selector: 'hello',
  template: `
  <form #myForm="ngForm">
    <input type="text" maxlength="20" name="patient" id="patient" [(ngModel)]="patient">
  </form>
  `,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
  @ViewChild('myForm') myForm: NgForm;
  patient: string;
}

A very simple component with a template driven form and a basic validation and binding. 一个非常简单的组件,具有模板驱动的表单以及基本的验证和绑定。

If you do this 如果你这样做

ngOnInit() {
  console.log(this.myForm.controls);
  setTimeout(() => console.log(this.myForm.controls));
}

You will see both undefined and { patient: FormControl } . 您将同时看到undefined{ patient: FormControl } This happens because you don't wait for the view to be initialized before doing your tests. 发生这种情况是因为您在执行测试之前不等待视图初始化。 This means that the test can't find the form control, and hence can't pass. 这意味着测试找不到表单控件,因此无法通过。

Now for the test itself : 现在进行测试:

import { Component } from '@angular/core';
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { By } from '@angular/platform-browser';

import { HelloComponent } from './hello.component';

import { FormsModule } from '@angular/forms';

describe('HelloComponent', () => {
  let fixture: ComponentFixture<HelloComponent>;
  let component: HelloComponent;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [FormsModule],
      declarations: [HelloComponent]
    });

    fixture = TestBed.createComponent(HelloComponent);
    component = fixture.debugElement.children[0].componentInstance;

    fixture.detectChanges();
  });

  it('should be invalid with more than 20 chars', async(() => {
    setTimeout(() => {
      component.myForm.controls['patient'].setValue('ddddddddddddddddddddd'); // 21
      fixture.detectChanges();
      expect(component.myForm.control.invalid).toEqual(true);
    });
  }));
});

the start is very basic, test bed is configured and changes are detected. 开始非常基本,已配置测试台并检测到更改。

Now comes the part where you test : you first must wait for the component to load with a timeout, then, you need to set the value on the form by using the framework : 现在是您要测试的部分:首先必须等待组件加载超时,然后才需要使用框架在表单上设置值:

component.myForm.controls['patient'].setValue('ddddddddddddddddddddd'); // 21

This inputs 21 d into the input, which is making it invalid. 此接口输入21 d到输入,这是使其无效。 After that, you need to trigger the changes detection, and now you can make your expectation with 之后,您需要触发更改检测,现在您可以使用

expect(component.myForm.control.invalid).toEqual(true);

This will take the form as a control, meaning it has all the properties and functions a FormControl has. 这将以表单作为控件,这意味着它具有FormControl拥有的所有属性和功能。 Among these, you can find the invalid property, which states if your control is in an invalid state. 其中,您可以找到invalid属性,该属性指出您的控件是否处于无效状态。

Again, I have to state that this kind of test is useless, because you basically try to see if the Framework is working properly. 同样,我必须指出这种测试是无用的,因为您基本上是在尝试查看框架是否正常运行。 That's not your job, that's Angular team's job. 那不是你的工作,那是Angular团队的工作。 If you want to test something, you should test that the form can't be submitted when it has an invalid state, which is a business rule (I guess) and prevents side effects (unlike this test). 如果您想测试某项内容,则应测试该表单处于无效状态时无法提交该表单,这是一种业务规则(我想),并且可以防止副作用(与该测试不同)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM