Aurelia 验证 - 表单加载了来自提取的数据 - 验证将完整字段评估为空
Aurelia Validation - Form is loaded with data from a fetch - validation evaluates full fields as empty
我有一个表单,我成功地加载了从提取中获取的数据。如果我随后单击该表单上的保存,Aurelia Validation 会将那些数据为空的表单文本字段评估为空,并将其显示为保存按钮下方的错误 - 如下图。
验证在空表单上完美运行,但对于加载了值的表单,就好像表单的行为就像它是空的一样。
当然,如果文本框中有字符,无论是通过键入还是从提取中加载,它应该在 "required" 的上下文中评估并通过?
目前它不是从抓取中加载的。
代码
这是打字稿视图模型:
import { HttpClient } from "aurelia-fetch-client";
import { autoinject, inject, NewInstance, PLATFORM } from "aurelia-framework";
import { Router, activationStrategy } from "aurelia-router";
import {
ValidationControllerFactory,
ValidationController,
ValidationRules,
validateTrigger
} from "aurelia-validation";
import { BootstrapFormRenderer } from "../../../../services/bootstrapFormRenderer/bootstrapFormRenderer";
//import from '../../../../services/customValidationRules/customValidationRules'
import { AuthService } from "../../../../services/auth/auth-service"
@autoinject
export class Client {
controller: ValidationController;
client = new ClientDetails;
job: Job;
visits = Array();
hasClientId: boolean;
heading: string = "New Client";
headingIcon: string = "fa-user-plus";
username: string;
constructor(
private authService: AuthService,
private router: Router,
private controllerFactory: ValidationControllerFactory
) {
this.router = router;
this.controller = controllerFactory.createForCurrentScope();
this.controller.addRenderer(new BootstrapFormRenderer());
this.controller.addObject(this)
this.controller.addObject(this.client);
}
// Required to reload new instance.
determineActivationStrategy() {
return activationStrategy.replace; //replace the viewmodel with a new instance
// or activationStrategy.invokeLifecycle to invoke router lifecycle methods on the existing VM
// or activationStrategy.noChange to explicitly use the default behavior
}
activate(parms, routeConfig) {
this.hasClientId = parms.id;
if (this.hasClientId) {
const headers = this.authService.header();
fetch("/api/Client/edit/" + parms.id, {
method: "GET",
headers
})
.then(response => response.json())
.then(data => {
this.client = data
})
this.heading = "Edit Client"; // An id was submitted in the route so we change the heading as well.
this.headingIcon = "fa-pencil-square-o";
}
return null;
}
submitClient() {
console.log("gets Here");
console.log("this.controller.validate(): ", this.controller.validate());
//this.controller.validate();
if (this.controller.validate()) {
console.log("Hi!");
}
}
rowSelected(jobId: number) {
let job = this.client.jobs.filter(f => f.id === jobId);
if (job && job.length > 0) {
var jobVisits = job.map(j => { return j.jobVisits; })[0];
this.visits = jobVisits;
}
}
}
export class ClientDetails {
clientId: number;
clientNo: number;
company: boolean;
companyName: string;
abn: string;
isWarrantyCompany: boolean;
requiresPartsPayment: boolean;
clientFirstName: string;
clientLastName: string;
email: string;
mobilePhone: string;
phone: string;
notes: string;
address: AddressDetails;
jobs: Job[];
bankName: string;
bankBSB: string;
bankAccount: string;
active: boolean;
deActivated: string;
activity: boolean;
dateCreated: string;
dateUpdated: string;
creatorId: number;
creatorName: string;
}
class Job {
id: number;
agentJobNo: number;
jobNo: number;
jobType: string;
jobVisits: Visit[]
numberOfVisits: number;
status: string;
}
class Visit {
jobVisitId: number;
dateCreated: string;
visitDate: string;
startTime: string;
endTime: string;
}
class AddressDetails {
address1: string;
address2: string;
suburb: string;
postcode: string;
stateShortName: string;
addressLocationId: number;
}
// Validation Rules.
ValidationRules
.ensure((a: ClientDetails) => a.companyName).required()
.when((a: ClientDetails) => a.company === true)
.withMessage('Company name is required if client is a company.')
.ensure((a: ClientDetails) => a.clientLastName).required()
.ensure((a: ClientDetails) => a.mobilePhone).required()
.on(ClientDetails)
提取在激活函数中,只有在提供了 id 时才提取。提取加载 "client" 返回的数据。这行得通,我有一个表格,其中显示了提取的所有数据。
但是,如果我单击 "Save" 按钮,即使 "lastName" 和 "mobilePhone" 这两个字段中有值,"submitClient()" 函数也会触发 "this.controller.validate()" 评估这些字段为空。
它不应该看到这些字段中有值吗?我在这里遗漏了什么吗?
视图如下所示 "lastName" - 请注意“& validate”存在。
<div class="col-md-6">
<div class="col-md-3">
<div class="form-group">
<label class="control-label pull-right" for="lastname">Last Name: </label>
</div>
</div>
<div class="col-md-9">
<div class="form-group">
<input type="text" value.bind="client.clientLastName & validate" class="form-control" id="lastname" placeholder="Last Name...">
</div>
</div>
</div>
从服务器加载现有客户端时,您将 this.client
属性 设置为一个简单的 JSON 对象。它将不再是 ClientDetails
的实例,因此验证规则将不起作用,因为它们仅适用于 ClientDetails
个实例。
您需要创建 ClientDetails
的新实例并从 fetch
返回的 data
对象填充它。它可以通过在 ClientDetails
中创建接受数据对象并映射到每个 ClientDetails
属性(this.clientId = data.clientId
等)的构造函数或映射方法来手动完成。
作为替代方案,您可以使用某种通用映射器函数,它可以通过 属性 名称进行映射。我对 TypeScript 不是很熟悉,但是 this SO question 有很多关于如何做到这一点的解决方案。
我有一个表单,我成功地加载了从提取中获取的数据。如果我随后单击该表单上的保存,Aurelia Validation 会将那些数据为空的表单文本字段评估为空,并将其显示为保存按钮下方的错误 - 如下图。
验证在空表单上完美运行,但对于加载了值的表单,就好像表单的行为就像它是空的一样。
当然,如果文本框中有字符,无论是通过键入还是从提取中加载,它应该在 "required" 的上下文中评估并通过?
目前它不是从抓取中加载的。
代码
这是打字稿视图模型:
import { HttpClient } from "aurelia-fetch-client";
import { autoinject, inject, NewInstance, PLATFORM } from "aurelia-framework";
import { Router, activationStrategy } from "aurelia-router";
import {
ValidationControllerFactory,
ValidationController,
ValidationRules,
validateTrigger
} from "aurelia-validation";
import { BootstrapFormRenderer } from "../../../../services/bootstrapFormRenderer/bootstrapFormRenderer";
//import from '../../../../services/customValidationRules/customValidationRules'
import { AuthService } from "../../../../services/auth/auth-service"
@autoinject
export class Client {
controller: ValidationController;
client = new ClientDetails;
job: Job;
visits = Array();
hasClientId: boolean;
heading: string = "New Client";
headingIcon: string = "fa-user-plus";
username: string;
constructor(
private authService: AuthService,
private router: Router,
private controllerFactory: ValidationControllerFactory
) {
this.router = router;
this.controller = controllerFactory.createForCurrentScope();
this.controller.addRenderer(new BootstrapFormRenderer());
this.controller.addObject(this)
this.controller.addObject(this.client);
}
// Required to reload new instance.
determineActivationStrategy() {
return activationStrategy.replace; //replace the viewmodel with a new instance
// or activationStrategy.invokeLifecycle to invoke router lifecycle methods on the existing VM
// or activationStrategy.noChange to explicitly use the default behavior
}
activate(parms, routeConfig) {
this.hasClientId = parms.id;
if (this.hasClientId) {
const headers = this.authService.header();
fetch("/api/Client/edit/" + parms.id, {
method: "GET",
headers
})
.then(response => response.json())
.then(data => {
this.client = data
})
this.heading = "Edit Client"; // An id was submitted in the route so we change the heading as well.
this.headingIcon = "fa-pencil-square-o";
}
return null;
}
submitClient() {
console.log("gets Here");
console.log("this.controller.validate(): ", this.controller.validate());
//this.controller.validate();
if (this.controller.validate()) {
console.log("Hi!");
}
}
rowSelected(jobId: number) {
let job = this.client.jobs.filter(f => f.id === jobId);
if (job && job.length > 0) {
var jobVisits = job.map(j => { return j.jobVisits; })[0];
this.visits = jobVisits;
}
}
}
export class ClientDetails {
clientId: number;
clientNo: number;
company: boolean;
companyName: string;
abn: string;
isWarrantyCompany: boolean;
requiresPartsPayment: boolean;
clientFirstName: string;
clientLastName: string;
email: string;
mobilePhone: string;
phone: string;
notes: string;
address: AddressDetails;
jobs: Job[];
bankName: string;
bankBSB: string;
bankAccount: string;
active: boolean;
deActivated: string;
activity: boolean;
dateCreated: string;
dateUpdated: string;
creatorId: number;
creatorName: string;
}
class Job {
id: number;
agentJobNo: number;
jobNo: number;
jobType: string;
jobVisits: Visit[]
numberOfVisits: number;
status: string;
}
class Visit {
jobVisitId: number;
dateCreated: string;
visitDate: string;
startTime: string;
endTime: string;
}
class AddressDetails {
address1: string;
address2: string;
suburb: string;
postcode: string;
stateShortName: string;
addressLocationId: number;
}
// Validation Rules.
ValidationRules
.ensure((a: ClientDetails) => a.companyName).required()
.when((a: ClientDetails) => a.company === true)
.withMessage('Company name is required if client is a company.')
.ensure((a: ClientDetails) => a.clientLastName).required()
.ensure((a: ClientDetails) => a.mobilePhone).required()
.on(ClientDetails)
提取在激活函数中,只有在提供了 id 时才提取。提取加载 "client" 返回的数据。这行得通,我有一个表格,其中显示了提取的所有数据。
但是,如果我单击 "Save" 按钮,即使 "lastName" 和 "mobilePhone" 这两个字段中有值,"submitClient()" 函数也会触发 "this.controller.validate()" 评估这些字段为空。
它不应该看到这些字段中有值吗?我在这里遗漏了什么吗?
视图如下所示 "lastName" - 请注意“& validate”存在。
<div class="col-md-6">
<div class="col-md-3">
<div class="form-group">
<label class="control-label pull-right" for="lastname">Last Name: </label>
</div>
</div>
<div class="col-md-9">
<div class="form-group">
<input type="text" value.bind="client.clientLastName & validate" class="form-control" id="lastname" placeholder="Last Name...">
</div>
</div>
</div>
从服务器加载现有客户端时,您将 this.client
属性 设置为一个简单的 JSON 对象。它将不再是 ClientDetails
的实例,因此验证规则将不起作用,因为它们仅适用于 ClientDetails
个实例。
您需要创建 ClientDetails
的新实例并从 fetch
返回的 data
对象填充它。它可以通过在 ClientDetails
中创建接受数据对象并映射到每个 ClientDetails
属性(this.clientId = data.clientId
等)的构造函数或映射方法来手动完成。
作为替代方案,您可以使用某种通用映射器函数,它可以通过 属性 名称进行映射。我对 TypeScript 不是很熟悉,但是 this SO question 有很多关于如何做到这一点的解决方案。