(代码已更新并修复)
我正在尝试构建一个表单并向控件组添加验证,以便我可以检查两个控件的组合是否存在于一个对象数组中。我有以下代码,但是当我尝试运行我的页面时,它会给我一个错误。
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 & Name Combo Already Exist</div>
</form>
</div>
答案 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);
}
});
}