【问题标题】:Adding validators in angular forms以角度形式添加验证器
【发布时间】:2018-11-09 06:23:54
【问题描述】:

我正在测试这个 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

我的组件中有这个:

    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);
                      })); 

现在我想通过检查 vaidator 来测试有效性。 console.log 只打印出没有验证器类型的表单控件,因为它没有找到它。

我在我的组件中为此字段添加了一个验证器:

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

但这不起作用。我在这里做错了吗?

谢谢!

【问题讨论】:

    标签: javascript html angular


    【解决方案1】:

    您的问题源于您没有按顺序做事并且不依赖框架进行测试。

    I made a sandbox 带有工作测试,请随意查看。现在解释一下:

    让我们从组件开始:

    @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;
    }
    

    一个非常简单的组件,带有模板驱动的表单以及基本的验证和绑定。

    如果你这样做

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

    您将看到undefined{ patient: FormControl }。发生这种情况是因为您在进行测试之前没有等待视图被初始化。这意味着测试找不到表单控件,因此无法通过。

    现在是测试本身:

    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);
        });
      }));
    });
    

    开始是非常基本的,测试台已配置并检测到更改。

    现在是你测试的部分:你首先必须等待组件加载超时,然后,你需要使用框架在表单上设置值:

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

    这会将 21 d 输入到输入中,这使其无效。之后,您需要触发更改检测,现在您可以使用

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

    这会将表单作为控件,这意味着它具有 FormControl 的所有属性和功能。其中,您可以找到invalid 属性,该属性表明您的控件是否处于无效状态。

    再次,我必须声明这种测试是没有用的,因为您基本上是尝试查看框架是否正常工作。那不是你的工作,那是 Angular 团队的工作。如果你想测试一些东西,你应该测试当表单处于无效状态时不能提交,这是一个业务规则(我猜)并防止副作用(不像这个测试)。

    【讨论】:

    • 但是为了测试的目的,我会测试它是否在某些无效的情况下输出错误。而且由于提交按钮在无效数据上被禁用,这意味着它不能汇总无效值
    • 我不能使用验证器来输出元素的类名吗?
    • 再一次,这种测试是没有用的,Angular 会根据您的条件显示错误消息并隐藏按钮。您无需测试 Angular 是否有效,只要您的业务逻辑符合您的期望即可。而不是测试 className,您应该直接测试元素是否通过 ViewChild 引用显示。
    • component.myForm.controls['paciente.nhc'].setValue 它说不能采用未定义的 setValue。我可以在控件内部放置 teh nhc 的 viewChld 的参考吗? ElementRef 应该是什么类型?
    • 我们为什么要从这个expect(fixture.nativeElement.querySelector('input[name="apellidos"]').className.includes('ng-invalid')).toEqual(true) ;对这种新型测试。我喜欢更多的类名称,因为你也可以测试原始和肮脏的
    猜你喜欢
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多