实例化期间Angular 2 FormBuilder错误

时间:2016-05-09 19:58:04

标签: typescript angular

(代码已更新并修复)

我正在尝试构建一个表单并向控件组添加验证,以便我可以检查两个控件的组合是否存在于一个对象数组中。我有以下代码,但是当我尝试运行我的页面时,它会给我一个错误。

  

EXCEPTION:ClientFormComponent实例化期间出错!   原始异常:TypeError:无法读取未定义的属性“长度”

我不确定为什么它无法访问我的数组的length属性。我的服务的“getClients()”方法在我的应用程序的其他地方工作得很好。任何想法都会很棒。

@Component({
    selector: 'client-form',
    templateUrl: './Scripts/typescript/client-form.component.html',
    directives: [FORM_DIRECTIVES],
    providers: [ClientService]
})

export class ClientFormComponent
{
    clientForm: ControlGroup;
    npi: AbstractControl;
    name: AbstractControl;

    constructor(private _clientService: ClientService, _fb: FormBuilder) {
        this.clientForm = _fb.group({ 'name': ['', Validators.compose([Validators.required])], 'npi': ['', Validators.compose([Validators.required, npiNumValidator, Validators.maxLength(10), Validators.minLength(10)])] }, { asyncValidator: this.npiNameDupValidator.bind(this) });
        this.name = this.clientForm.controls['name'];
        this.npi = this.clientForm.controls['npi'];
    }
    

    clientList: Client[];
    active = true;


    onSubmit(value: Client) {
        this._clientService.addDeleteClient(value, true)
            .subscribe(
            client => this.clientList.push(client));        
    }    

    npiNameDupValidator(group: ControlGroup) {
        return new Promise((resolve, reject) => {
            let name = group.controls['name'];
            let npi = group.controls['npi'];
            var found = false;

            this._clientService.getClients().subscribe(clients => {                
                for (var i = 0; i < clients.length; i++) {
                    alert(clients[i].name + ':' + name.value);
                    alert(clients[i].npi + ':' + npi.value);

                    if (clients[i].name == name.value && clients[i].npi == npi.value) {
                        found = true;
                        break;
                    }
                }

                if (found) {
                    alert('Found!');
                    resolve({ npiNameDupe: true });
                }
                else {
                    resolve(null);
                }
            });            
        });
    }
}


function npiNumValidator(control: Control): { [s: string]: boolean } {
    if (isNaN(control.value)) {
        return { npiNAN: true };
    }
}

我的模板HTML:

<div class="container">
    <form *ngIf="active" (ngSubmit)="onSubmit(clientForm.value)" [ngFormModel]="clientForm">
        <div class="form-group" style="float: left;">
            <label for="clientid">Client Id:</label>
            <input placeholder="QDX"id="clientid" type="text" class="form-control"  [ngFormControl]="clientForm.controls['name']">
            <div *ngIf="name.hasError('required') && name.touched"
                 class="alert alert-danger">Client ID is required</div>
            <div *ngIf="name.hasError('npiNAN')"
                 class="alert alert-danger">NPI must be a number</div>
            
        </div>

        <div class="form-group" style="float: left; padding-left: 10px;">
            <label for="npi">NPI:</label>
            <input placeholder="0123456789" maxlength="10" id="npi" type="text" class="form-control" [ngFormControl]="clientForm.controls['npi']">
            <div *ngIf="npi.hasError('required') && npi.touched"
                 class="alert alert-danger">NPI is required</div>
            <div *ngIf="npi.hasError('npiNAN') && npi.touched"
                 class="alert alert-danger">NPI must be a number</div>
            <div *ngIf="npi.hasError('minlength') && npi.touched"
                 class="alert alert-danger">NPI must be 10 characters</div>
            
        </div>
        
        <div style="float: left; margin: 25px 0 0 10px;">
            <button type="submit" class="btn btn-default" [disabled]="!clientForm.valid">Add</button>
        </div>
        <br style="clear:both;" />
        <div *ngIf="clientForm.hasError('npiNameDupe')"
             class="alert alert-danger">NPI &amp; Name Combo Already Exist</div>
    </form>
</div>

2 个答案:

答案 0 :(得分:2)

由于getClients()是一个可观察的,你需要设置订阅回调的长度。

var clis: Client[];
var length = 0;
this._clientService.getClients().subscribe(clients => {
    clis = clients;
    length = clis.length;
});

这可确保在将数据返回到您的订阅后正确设置长度。

至于为什么你首先得到错误,你还没有初始化你的数组。您需要实际提供一个默认值,因为当前它是未定义的,当您尝试检查长度时会抛出错误。

var clis: Client[] = [];

答案 1 :(得分:1)

我认为您尝试实现异步验证器。您应该使用asyncValidator属性代替validator

_fb.group({
  'name': ['', Validators.compose([Validators.required])],
  'npi': ['', Validators.compose([Validators.required, (...)])]
}, { asyncValidator: this.npiNameDupValidator.bind(this) });

我会以这种方式重构你的验证器:

npiNameDupValidator(group: ControlGroup) {
  return new Promise((resolve, reject) => {
    let name = group.controls['name'];
    let npi = group.controls['npi'];

    this._clientService.getClients().subscribe(clients => {
      var clis = clients;
      var length = clis.length;
      var found = (...); // your processing here

      if (found) {
        resolve({ npiNameDupe: true });
      } else {
        resolve(null);
      }
  });
}