【问题标题】:Mark fields not valid as red with knockout/durandal用淘汰赛/杜兰达尔将无效字段标记为红色
【发布时间】:2013-03-16 04:23:14
【问题描述】:

我正在学习淘汰赛、Durandal 和 Breeze,感谢 John Papa 的 JumpStart SPA 视频,我很高兴。所以我检查了这个项目的代码,现在我正在尝试更改验证机制。

此时,当保存更改时,如果保存失败,我们会收集错误并显示 toast 并恢复错误。

我想要实现的是:

  • 能够在视图中以红色(背景色)标记无效字段

  • 当显示带有验证错误恢复的 toast 时(类似于:'保存失败:需要事务 Nr')我想用更友好的名称替换属性名称(类似于'保存失败:事务数字是必需的')

这是datacontext.js中验证的部分代码:

var saveChanges = function () {
    return manager.saveChanges()
        .then(saveSucceeded)
        .fail(saveFailed);

    function saveSucceeded(saveResult) {
        log('Saved data successfully', saveResult, true);
    }

    function saveFailed(error) {
        var msg = 'Save failed: ' + getErrorMessages(error);
        logError(msg, error);
        error.message = msg;
        throw error;
    }
};

function getErrorMessages(error) {
    var msg = error.message;
    if (msg.match(/validation error/i)) {
        return getValidationMessages(error);
    }
    return msg;
}

function getValidationMessages(error) {
    try {
        //foreach entity with a validation error
        return error.entitiesWithErrors.map(function (entity) {
            // get each validation error
            return entity.entityAspect.getValidationErrors().map(function (valError) {
                // return the error message from the validation
                return valError.errorMessage;
            }).join('; <br/>');
        }).join('; <br/>');
    }
    catch (e) { }
    return 'validation error';
}

有人能指出我正确的方向吗?

提前致谢。


编辑:

要重现问题:单击左侧边栏上的 Transports + recherche avancee + 列表中的任何项目 + 右侧:清除一些输入(如 Numero d'affaire 如下截图所示),然后单击“Enregistrer”。然后调用保存按钮。在那里我需要检查 ko.validation.group 是否有无效输入,但它不起作用。

【问题讨论】:

  • 如果您想在客户端保持良好的视图/视图模型分离和 MVVM 模式,我认为 Evan 引用的 Knockout Validation 是一个不错的选择,因为它可以验证视图模型数据。

标签: knockout.js breeze durandal


【解决方案1】:

前段时间,我发布了一个辅助函数,它扩展了可观察属性以添加基于微风验证器的验证。使用该助手,您可以在无效输入上实现红色:

Translate breeze validation messages

第二个问题我无法帮助您,我知道您可以自定义验证消息,但我认为使用默认验证器无法设置友好名称以显示在消息上。

更新:

我要做的第一件事是创建一个公开函数的辅助模块(更新版本):

define([],
function () {
"use strict";
var foreignKeyInvalidValue = 0;

function addValidationRules(entity) {
    var entityType = entity.entityType,
        i,
        property,
        propertyName,
        propertyObject,
        validators,
        u,
        validator,
        nValidator;

    if (entityType) {
        for (i = 0; i < entityType.dataProperties.length; i += 1) {
            property = entityType.dataProperties[i];
            propertyName = property.name;
            propertyObject = entity[propertyName];
            validators = [];

            for (u = 0; u < property.validators.length; u += 1) {
                validator = property.validators[u];
                nValidator = {
                    propertyName: propertyName,
                    validator: function (val) {
                        var error = this.innerValidator.validate(val, { displayName: this.propertyName });
                        this.message = error ? error.errorMessage : "";
                        return error === null;
                    },
                    message: "",
                    innerValidator: validator
                };
                validators.push(nValidator);
            }
            propertyObject.extend({
                validation: validators
            });
        }

        for (i = 0; i < entityType.foreignKeyProperties.length; i += 1) {
            property = entityType.foreignKeyProperties[i];
            propertyName = property.name;
            propertyObject = entity[propertyName];

            validators = [];
            for (u = 0; u < property.validators.length; u += 1) {
                validator = property.validators[u];
                nValidator = {
                    propertyName: propertyName,
                    validator: function (val) {
                        var error = this.innerValidator.validate(val, { displayName: this.propertyName });
                        this.message = error ? error.errorMessage : "";
                        return error === null;
                    },
                    message: "",
                    innerValidator: validator
                };
                validators.push(nValidator);
            }
            propertyObject.extend({
                validation: validators
            });
            if (!property.isNullable) {
                //Bussiness Rule: 0 is not allowed for required foreign keys
                propertyObject.extend({ notEqual: foreignKeyInvalidValue });
            }
        }
    }
}

return {
    addValidationRules: addValidationRules
};
});

然后,我为每个微风实体类型 (http://www.breezejs.com/documentation/extending-entities) 定义一个初始化程序。示例:

define(['app/validatorHelper', 'knockout'],
function (vHelper, ko) {
"use strict";
var constructor = function () {
},

    initializer = function indicadorInitializer(entity) {
        vHelper.addValidationRules(entity);
    };

return {
    constructor: constructor,
    initializer: initializer
};
});

最后,在某个地方(我在我的数据服务模块中的一个 init 函数上做这件事),我正在注册初始化程序(http://www.breezejs.com/documentation/extending-entities):

//store comes from: manager = breezeconfig.createManager(),
//    store = manager.metadataStore,
store.registerEntityTypeCtor("Palanca", domain.palanca.constructor, domain.palanca.initializer);

我在获取元数据之前完成了所有这些工作。

希望对你有帮助。

更新 2:

我发现了问题,你的淘汰验证版本不是最后一个。

在从http://ericmbarnard.github.com/Knockout-Validation/下载的文件中,第349行是:

exports.rules[ruleName] = ruleObj;

在您的文件中,等效的行(函数 addAnonymousRule)是:

ko.validation.rules[ruleName] = {
    validator: ruleObj.validator,
    message: ruleObj.message || 'Error'
};

我认为最新版本应该可以工作。

更新 4:

这是要保存的代码:

vmAddPalanca.prototype.saveChangesCmd = ko.asyncCommand({
    execute: function (palanca, complete) {
        var validationErrors = ko.validation.group(palanca);
        if (validationErrors().length === 0) {
            dataservice.saveChanges()
            .then(saveChangesSuccess)
            .fail(saveChangesFail)
            .fin(complete);
        } else {
            validationErrors.showAllMessages(true);
            toastr.error("Debe corregir los errores antes de poder guardar");
            complete();
        }
    },
    canExecute: function (isExecuting) {
        return !isExecuting && dataservice.hasChanges();
    }
});

【讨论】:

  • 我正忙于调试您的代码,但出现错误:propertyObject.extend({ validation: validators });说检索数据时出错。
  • 可能需要一些背景知识。在之前的一篇文章中,我展示了我如何使用验证助手:stackoverflow.com/questions/13662446/… 基本情况是我正在为我的微风实体使用初始化程序,并且在初始化程序内部我正在调用该函数。我会更新我的答案给你一个详细的答案。
  • 是的,我添加了淘汰赛验证。实际上,对于您的代码的第一个版本(使用 indicadorInitializer),我没有收到任何错误。但是使用您的代码的第二个版本(使用 addValidationRules),我得到了上面给出的错误。知道为什么吗?
  • 我不知道,如果你能把代码放在某个地方,我可以看看。
  • 这里是下载包含 VS2012 解决方案的 zip 的链接:dropbox.com/s/rgtkm5xkkoem2cb/TRANSPORTBOEK.zip 只需打开解决方案,运行它,在左侧边栏上,单击“Transports”+“Recherche avancée”,然后它会给出一个错误。问题位于 App/services/model.js 第 64 + 90 行。感谢您的帮助。如果我评论这些行并替换为下面的行,则没有错误。
猜你喜欢
  • 2013-11-16
  • 2013-07-20
  • 2013-11-14
  • 2015-05-25
  • 2013-10-19
  • 2013-08-31
  • 1970-01-01
  • 2014-03-19
  • 2013-04-22
相关资源
最近更新 更多