代码之家  ›  专栏  ›  技术社区  ›  Maniraj Murugan

形状验证(角度)

  •  2
  • Maniraj Murugan  · 技术社区  · 6 年前

    我使用角度无功形式,并使距离输入字段有两个输入框称为 From To .

    HTML:

    <form [formGroup]="form">
      <button (click)="addRow()">Add</button>
      <div formArrayName="distance">
        <div
          *ngFor="let item of form.get('distance').controls; let i = index"
          [formGroupName]="i"
          style="display: flex"
        >
          <input type="number" placeholder="From" formControlName="from" />
          <div><input type="number" placeholder="To" formControlName="to" /></div>
        </div>
      </div>
      <br /><br />
      <button type="submit" [disabled]="!form.valid">Submit</button>
    </form>
    

    TypeScript:

    ngOnInit() {
      this.form = this.fb.group({
        distance: this.fb.array([]),
      });
      this.addRow()
    }
    
    addRow() {
      const control = this.form.controls.distance as FormArray;
      control.push(this.fb.group({
        from: ['',Validators.required],
        to: ['',Validators.required]
      }));
    }
    

    在这里,您可以看到默认情况下的两个输入框 from to .

    顶部有一个“添加”按钮,单击“添加”按钮后,将添加具有相同输入字段的行,并形成数组形式。

    这里我需要限制那个用户 不允许 输入前一行 值,也不是小于该值的值。

    例如,

    在第一行中,如果用户输入以下值,如 分别从和到,

      "distance": [
        {
          "from": 0,
          "to": 5
        }
      ]
    

    单击“添加”并在第二行中 需要限制输入框用户添加5和小于5的值(这意味着已经输入了这些值)。

    所以这是无效的,

    {
      "distance": [
        {
          "from": 0,
          "to": 5
        },
        {
          "from": 5,
          "to": 10
        }
      ]
    }
    

    在这里 "from": 5, "from": 4(or)3(or)2(or)1 ,第二行中的任何内容都无效。

    只有6个且大于6个有效。

    同样,对于每一行,它需要检查前一行的值,并且需要进行验证。

    请帮助我实现这种类型的验证,以限制用户不输入前一行的值(或)小于当前行的“从值”中的值。

    工作示例: https://stackblitz.com/edit/disable-group-control-value-on-another-control-value-for-j58atx

    编辑:

    尝试输入更改,例如,

    <input type="number" (input)="onInputChange($event.target.value)" placeholder="From" formControlName="from">
    

    在链接中 https://stackblitz.com/edit/disable-group-control-value-on-another-control-value-for-ymfpkj 但不确定我是否正确……

    如果程序错误,请更改。

    2 回复  |  直到 6 年前
        1
  •  2
  •   Eliseo    6 年前

    最后我决定把这两个条件分开。看见 new stackblitz

      ngOnInit() {
        this.form = this.fb.group({
          distance: this.fb.array([], this.distanceValidator()),
        });
        this.addRow()
      }
    
      addRow() {
        const control = this.form.controls.distance as FormArray;
        control.push(this.fb.group({
          from: ['', Validators.required],
          to: ['', Validators.required]
        }, { validator: this.greaterValidator() }));
      }
      setDefault() {
        const control = this.form.controls.distance as FormArray;
        this.default.forEach(data => {
          control.push(this.fb.group({
            from: [data.from, Validators.required],
            to: [data.to, Validators.required]
          }, { validator: this.greaterValidator() }));
        });
      }
      greaterValidator() {
        return (fa: FormGroup) => {
          return fa.value.to && fa.value.to < fa.value.from ? { error: "from greater than to" } : null;
        }
      }
      distanceValidator() {
        return (fa: FormArray) => {
          let ok = true;
          for (let i = 1; i < fa.value.length; i++) {
            ok = (!fa.value[i].from || fa.value[i].from > fa.value[i - 1].to) && (!fa.value[i].to || fa.value[i].to > fa.value[i - 1].from);
            if (!ok)
              return { error: "from/to yet included", index: i }
          }
          return null
        }
      }
    

    和html

    <form [formGroup]="form">
        <button (click)="addRow()">Add</button>
      <div formArrayName="distance" >
        <div 
          *ngFor="let item of form.get('distance').controls; let i = index" 
          [formGroupName]="i" 
          style="display: flex">
          <input type="number" 
            placeholder="From" 
            formControlName="from">
          <div>
            <input type="number"
              placeholder="To" 
              formControlName="to">
          </div>
          <span *ngIf="item.errors">*</span>
          <span *ngIf="form.get('distance')?.errors && form.get('distance')?.errors.index==i">**</span>
        </div>
      </div>
      <div *ngIf="form.get('distance')?.errors">{{form.get('distance')?.errors.error}}</div>
      <br><br>
      <button type="submit" [disabled]="!form.valid"> Submit </button>
    </form>
    <button (click)="setDefault()"> Set Default Values </button>
    

    更新 :事实上,只有在发现错误时才可以控制更多。 另外,如果“从”和“到”都是空的,不要给出错误。为了避免这种情况,我们可以“转换”成数字,写

    let ok = (!fa.value[i].from || fa.value[i].from > +fa.value[i - 1].to)
            && (!fa.value[i].to || fa.value[i].to > +fa.value[i - 1].from);
    

    (见+fa.value[i-1]中的“+”,to和+fa.value[i-1],from

    好吧,当我们决定发送的错误时,假设您有6行,行在位置0、位置3和位置4(0是第一行)发送一个错误,就像

    {error:"there are errors",indexError:",0,3,4,"}
    

    这允许在*ngfor中写一些

      <span *ngIf="form.get('distance')?.errors && 
          form.get('distance')?.errors.indexError.indexOf(','+i+',')>=0">
           **
      </span>
    

    嗯,我们的距离验证器变成了

      distanceValidator() {
        return (fa: FormArray) => {
          let indexError:string="";
          for (let i = 1; i < fa.value.length; i++) {
            let ok = (!fa.value[i].from || fa.value[i].from > +fa.value[i - 1].to) && (!fa.value[i].to || fa.value[i].to > +fa.value[i - 1].from);
            if (!ok)
              indexError+=','+i;
          }
          return indexError?{error:"there are errors",indexError:indexError+','}:null
        }
    

    有人认为最好返回一个错误数组,但这不允许以简单的方式知道有错误的行。有些错误。查找(x=>x.id==i)不起作用,因为无法在插值中使用查找。

    的确,只将一行与之前的inmediate进行比较。在使用for(让j=i-1;j>0;j++)ok=ok&…-之前可以检查所有内容,但我认为这不是必要的,我们在代码上必须小心谨慎。记住,函数DistanceValidator执行了多次 看到另一个 stackblitz

        2
  •  1
  •   Eliseo    6 年前

    只需使用自定义验证(我在同一组件中选择验证

    ngOnInit() {
        this.form = this.fb.group({
          distance: this.fb.array([], this.distanceValidator()),
        });
        this.addRow()
      }
      distanceValidator() {
        return (fa: FormArray) => {
          let ok = true;
          let ok2 = fa.value.length ? (!fa.value[0].to || !fa.value[0].from) || fa.value[0].to > fa.value[0].from : true;
          if (!ok2)
            return { error: "from greater than to" }
          for (let i = 1; i < fa.value.length; i++) {
            if (fa.value[i].from && fa.value[i].to )
            {
            ok = (fa.value[i].from > fa.value[i - 1].to || fa.value[i].to < fa.value[i - 1].from);
            ok2 = (fa.value[i].to > fa.value[i].from);
            if (!ok)
              return { error: "from/to yet included" }
            if (!ok2)
              return { error: "from greater than to" }
            }
          }
          return ok && ok2 ? null : !ok?{ error: "from yet included" }:{ error: "from greater than to" }
        }
      }
    

    你可以像其他人一样看到错误。

     <div *ngIf="form.get('distance')?.errors">
         {{form.get('distance')?.errors.error}}
     </div>
    

    见[Stackblitz Forked][1]