无法为使用角度的字段设置动态验证

时间:2018-10-22 03:35:45

标签: angular typescript

我正在面对现有应用程序的问题,以下是我的情况 我具有以下JSON格式

.html代码

<div class="panel-group" id="accordion">
    <div *ngFor="let property of Tree.properties">
      <div class="panel panel-default">
        <div class="panel-heading">
          <h4 class="panel-title">
            <a class="link" data-toggle="collapse" data-parent="#accordion" href="#dataCatg-{{property.name}}">
              <div *ngIf="property.required">
                <span class="glyphicon glyphicon-chevron-right"></span>{{property.name}}
              </div>
              <div *ngIf="!property.required">
                <span class="glyphicon glyphicon-chevron-right"></span>{{property.name}}
              </div>
            </a>
          </h4>
        </div>
        <div id="dataCatg-{{property.name}}" class="panel-collapse collapse">
          <div class="panel-body">
            <ul class="list-group">
              <li class="list-group-item" *ngFor="let prop of property.details">
                <div *ngIf="prop.details.visible">
                  <div class="row">
                    <div class="col-md-4">
                      <div *ngIf="data.includes(prop.name)">
                        <label class="inline-label" for="{{prop.name}}">{{prop.name}}</label>
                      </div>
                      <div *ngIf="!data.includes(prop.name) ">
                        <label class="inline-label " for="{{prop.name}} ">{{prop.name}}</label>
                      </div>
                    </div>
                  <div class="col-md-8 ">
                      <div *ngIf="!Edit">
                        <span *ngIf="formVisible && metaDataTemplateMap[selectedFile]!==undefined ">
                          <input id="{{prop.name}}" type="{{prop.details.type}} " [(ngModel)]="Data[prop.name]" class="form-control ">
                        </span>
                      </div>
                      <div *ngIf="Edit">
                        <div *ngIf="prop.details.group ">
                          <span *ngIf="formView">
                            <!--need-->
                            <input id="{{prop.name}}" type="{{prop.details.type}}" [(ngModel)]="Edit[prop.name]" (ngModelChange)="Edit($event)" style=" border-radius:0;"
                             class="form-control">
                          </span>
                        </div>
                        <div *ngIf="!prop.details.group ">
                          <input id="{{prop.name}}" type="text " style=" border-radius:0" class="form-control " readonly>
                        </div>
                     </div>
                    </div>
                  </div>
                </div>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>

.ts代码

Data(res) {


    this.Tree['Properties'] = [];

    for (let property in res.properties) {

      var prop = res.properties[property];
      if (prop['properties'] !== undefined) {
        let temp= {};
        if (res['required'].indexOf(property) !== -1) {
          temp['required'] = true;
        }
        else {
          temp['required'] = false;
        }
        temp['name'] = property;
        let template = {};
        temp['details'] = [];
        for (let nestedProps in prop.properties) {
          let nestedProp = {};
          nestedProp['name'] = nestedProps;

          if (prop.properties[nestedProps]['type'] == 'string' || prop.properties[nestedProps]['type'] == 'date-time') {
            prop.properties[nestedProps]['type'] = 'text';
            template[nestedProps] = '';
          }

          if (prop.properties[nestedProps]['type'] == 'integer') {
            prop.properties[nestedProps]['type'] = 'number';
            template[nestedProps] = 0;
          }

          if (prop.properties[nestedProps]['type'] == 'array') {
            prop.properties[nestedProps]['type'] = 'array';
            template[nestedProps] = '';
          }
          if (prop.properties[nestedProps]['group'] == true) {
            if (this.Edit[property] == undefined)
              this.Edit[property] = {};
            this.Edit[property][nestedProps] = '';
          }

          nestedProp['details'] = prop.properties[nestedProps];

          temp['details'].push(nestedProp);
        }
        this.Data[property] = template;
        this.Tree['Properties'].push(temp);
      }
      if (prop['properties'] == undefined) {
        let temp = {};
        if (res['required'].indexOf(property) !== -1) {
          temp['required'] = true;
        }
        else {
          temp['required'] = false;
        }
        temp['name'] = property;
        if (prop['type'] == 'string' || prop['type'] == 'date-time') {
          prop['type'] = 'text';
          this.Data[property] = '';
        }

        if (prop['type'] == 'number') {
          prop['type'] = 'integer';
          this.Data[property] = 0;
        }

        if (prop['group'] == true) {
          this.Edit[property] = '';
        }
        temp['details'] = prop;
        this.Tree['Others'].push(temp);
      }
    }


  }

这里我想要的是1.如果您在JSON中看到了

"required": [
    "host", 
    "quantity", 
    "id"
], 

在生成字段时,必须使用模板或反应形式方法来检查上述字段是否为空,如果字段为空,那么如何让用户知道字段为空,我该如何完成这个吗?

1 个答案:

答案 0 :(得分:5)

  

目标

未经ReactiveTemplate方法验证动态生成的表单输入。

  

解决方案

Directive将是此类要求的最佳选择。 Directive有助于将复杂的工作分解成小的独立任务。让我们看看如何实现它。

下面提供的实现无需更改现有代码。

1。验证服务

import { Injectable } from '@angular/core';

@Injectable()
export class ValidateService {

  errors = {};

  validate(key: string, value: object) {
    this.errors[key] = value;
  }

  getErrors() {
    let errorList = [];
    Object.keys(this.errors).forEach(key => {
      let value = this.errors[key];
      if ((value == undefined || value == '')  && this.required.find(item=>item == key)) {
        errorList.push({ name: key, error: key + " Field is required" })
      }
    });
    return errorList;
  }

   //All required fields can be maintained here
  required = [
    "host",
    "quantity",
    "id"
  ]

}

2。验证指令

ValidateDirective负责收集input控件的当前值(如果发生任何更改)。该信息将被传递到服务类ValidationService

import { Directive, Host, Input, OnChanges, SimpleChanges, ViewContainerRef, AfterViewInit } from '@angular/core';
import { ValidateService } from './validate.service';

@Directive({
  selector: '[validate]'
})
export class ValidateDirective implements OnChanges {

  constructor(private service: ValidateService, private containerRef: ViewContainerRef) {

  }

  @Input("ngModel") model;

  @Input("validate") element;

  ngOnChanges(changes: SimpleChanges) {

    setTimeout(() => {
      this.service.validate(this.containerRef.element.nativeElement.id, changes.model.currentValue);
    })
  }

}

3。指令用法

ValidateDirective可以与具有idngModel的任何输入控件一起使用。

例如:

<input [validate] id="{{prop.name}}" type="{{prop.details.type}}" [(ngModel)]="Edit[prop.name]" (ngModelChange)="Edit($event)" style=" border-radius:0;" class="form-control">

4。组件ts

ValidateService将被注入组件以获取错误列表。

constructor(private service:ValidateService) {}

  public get errors(){
    return this.service.getErrors();
  }

5。显示错误

由于所有错误都在组件中可用,因此可以在html中显示。

ex:

 <li *ngFor="let error of errors">
     {{error.error}}
 </li>  
  

注意-有很多可以进一步增强的功能,例如

     
    
        
  1. 将自定义消息传递到Directive
  2.     
  3. Required field list可以作为@Input传递给指令
  4.     
  

有效的示例演示在这里-https://stackblitz.com/edit/angular-xnbzqd