【问题标题】:Aurelia Validation Gives Error: TypeError: Object.defineProperty called on non-objectAurelia 验证给出错误:TypeError:Object.defineProperty 在非对象上调用
【发布时间】:2017-08-04 10:09:37
【问题描述】:

我正在尝试对 Aurelia 组件进行基本的 Aurelia 验证,但出现错误。

打字稿是:

import { bindable, inject, NewInstance } from 'aurelia-framework';
import { HttpClient } from 'aurelia-fetch-client';
import { validationMessages, ValidationRules, ValidationController } from 'aurelia-validation';

@inject(HttpClient, NewInstance.of(ValidationController))
export class PersonDetail {
    @bindable currentPerson: Person;
    private httpClient: HttpClient;
    public controller: ValidationController;

    constructor(http: HttpClient, controller: ValidationController) {
        this.httpClient = http;

        this.controller = controller;
        validationMessages['lastNameReq'] = 'You must enter a last name';
        ValidationRules.ensure('LastName').minLength(3).required().withMessageKey('lastNameReq').on(this.currentPerson);

    }

    saveToDb() {
        this.controller.validate()
            .then(v => {
                if (v.valid) {

                    // this.httpClient...(do stuff)
                }
             }
        }
}

html 是:

<template bindable="currentPerson">

    <form submit.delegate="saveToDb()">
        <p>First Name: <input type="text" class="form-control" value.bind="currentPerson.FirstName"></p>
        <p>Last Name: <input type="text" class="form-control" value.bind="currentPerson.LastName & validate"></p>
        <p>Middle Name: <input type="text" class="form-control" value.bind="currentPerson.MiddleName"></p>
        <p>Gender: <input type="text" class="form-control" value.bind="currentPerson.Sex"></p>
        <p>DOB: <input type="text" class="form-control" value.bind="person.DOB"></p>
        <p>Mobile Phone: <input type="text" class="form-control" value.bind="currentPerson.MobilePhnNbr"></p>
        <p>Email: <input type="text" class="form-control" value.bind="currentPerson.EmailAddr"></p>

        <button type="submit" class="btn-primary">Save to Database</button>
        <ul if.bind="controller.errors">
            <li repeat.for="error of controller.errors">
                ${error.message}
            </li>
        </ul>
    </form>
</template>

运行这个我得到以下错误:

aurelia-logging-console.js:47 错误 [app-router] 类型错误: Object.defineProperty 在非对象上调用 在 Function.defineProperty() 在 Function.29.Rules.set (rules.js:14) 在 FluentEnsure.48.FluentEnsure.on (validation-rules.js:347) 在 FluentRuleCustomizer.48.FluentRuleCustomizer.on (validation-rules.js:95) 在 PersonDetail.app/components/people/person-detail.PersonDetail.bind (person-detail.ts:27) 在 View.bind (aurelia-template.js:1400) 在 Controller.bind (aurelia-template.js:3394) 在 View.bind (aurelia-templating.js:1406) 在 Controller.bind (aurelia-template.js:3394) 在 Controller.automate (aurelia-templating.js:3339)

如果我将 ValidationRules 行更改为:

ValidationRules.ensure('currentPerson.LastName').minLength(3).required().withMessageKey('lastNameReq').on(this);

然后我不再收到错误,但验证也不起作用(当我清空姓氏字段时 this.controller.validate() 返回有效)。这与 LStarky 在这里发现的内容相符:Aurelia Validation not working with object properties。但是,如果我实施他的解决方案,我会收到上述错误。

【问题讨论】:

  • this.curentPerson 属性在ValidationRules.ensure 行运行时是否未定义?我可能是错的,纯粹是根据错误猜测。
  • 嗨@adiga 是的,没错,它是未定义的。我想出了下面的解决方案。
  • 您是否尝试过将ValidationRules 应用于Person 类本身,而不是该类的每个实例?像这样:ValidationRules.ensure('LastName').minLength(3).required().withMessageKey('lastNameReq').on(Person)
  • 我试过了,但是得到了一个打字稿错误 TS2693: 'Person' 只指一种类型,但在这里被用作一个值。 Aurelia 文档说您应该能够做到这一点。
  • 好的 - 通过制作 Person 和导出类而不是 Interface 并将其导入 ts 文件来设法消除该错误。然而,验证没有工作! :-/

标签: javascript validation aurelia


【解决方案1】:

上面的视图/视图模型对被用作页面中的自定义元素 - 它是主详细信息窗口的详细信息部分。这意味着第一次创建页面和自定义元素时 currentPerson 属性未定义,因此在该属性上创建验证规则时出现错误。

此外,由于每次更改主列表中的行时 currentPerson 都会更改,我发现每次发生这种情况时我都必须创建验证规则。

所以解决方案是让 currentPerson 可观察并在 currentPersonChanged 方法中设置验证规则。最终代码如下:

import { bindable, inject, NewInstance, observable } from 'aurelia-framework';
import { HttpClient } from 'aurelia-fetch-client';
import { validationMessages, ValidationRules, ValidationController } from 'aurelia-validation';

@inject(HttpClient, NewInstance.of(ValidationController))
export class PersonDetail {
    @bindable @observable currentPerson: Person;
    private httpClient: HttpClient;
    public controller: ValidationController;

    constructor(http: HttpClient, controller: ValidationController) {
        this.httpClient = http;

        this.controller = controller;
        validationMessages['lastNameReq'] = 'You must enter a last name';    
    }

    currentPersonChanged() {
        if (this.currentPerson) {
            ValidationRules.ensure('LastName').minLength(3).required().withMessageKey('lastNameReq').on(this.currentPerson);
        }
    }

    saveToDb() {
        this.controller.validate()
            .then(v => {
                if (v.valid) {

                    // this.httpClient...(do stuff)
                }
             }
        }
}

【讨论】:

    【解决方案2】:

    通常您在bind() 方法中设置您的验证规则,特别是如果您要验证的对象-this.currentPerson-是@bindable,因为在调用构造函数时它不会有值。

    constructor(http: HttpClient, controller: ValidationController) {
        this.httpClient = http;
    
        this.controller = controller;
        validationMessages['lastNameReq'] = 'You must enter a last name';
    }
    
    bind() {
        ValidationRules.ensure('LastName').minLength(3).required().withMessageKey('lastNameReq').on(this.currentPerson);
    }
    

    根据您的评论,当父/容器加载元素时,您似乎没有设置当前人员。有几种方法可以解决这个问题:

    1. 您可以使用if 绑定,该绑定仅在附加人员时创建人员自定义元素(详细信息部分)。 (在父母中:&lt;person-detail if.bind="currentPerson"&gt;&lt;person-detail&gt;)。 if bindings 实际上在结果为 true 时将元素添加/删除到 DOM 中,因此只有当 person 对象具有值时才会实例化和绑定视图模型
    2. 您可以在PersonDetail 类中查看绑定的人员对象,并且只有在它具有非空值时才调用验证规则。这有点棘手,因为您应该只设置一次验证规则,但有时这是要走的路。使用名为currentPersonChanged(newVal, oldVal) 的函数,它会自动为您调用。

    如果这不起作用,请告诉我!

    【讨论】:

    • 您好。抱歉,我应该提到我也在绑定事件中尝试过,但我仍然遇到同样的错误。在这个方法中 this.currentPerson 仍然是未定义的。我同意您希望它在这一点上具有价值。上述组件用作主/明细页面的明细部分,当您在主部分中选择记录时设置 currentPerson。我认为问题与此设置有关。我会继续玩它的。
    • 哦,我看到你已经找到了解决方案 #2!如果可以的话,我会尝试 #1,因为这是一种更好的方法。
    • #1 是一个很好的建议,但我认为最好的方法是对 Person 类型进行验证,正如问题下方的 convo 中所讨论的那样。不幸的是,我无法让它发挥作用。
    • 我在上面回答了,但你把它放在哪里取决于。如果人里面有另一个对象等等,你想要那个对象的自定义元素的规则,而不是父元素。
    猜你喜欢
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-09
    • 2020-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多