Mark fields not valid as red with knockout/durandal

亡梦爱人 提交于 2019-12-05 02:25:36

问题


I am learning knockout, Durandal and Breeze and thanks to the JumpStart SPA video from John Papa this is a pleasure. So I examine the code of this project and right now I am trying to change the validation mechanism.

At this time, when saving changes, if the save failed, we collect the errors and display a toast with a resume of the errors.

What I would like to achieve is:

  • having the ability to mark fields not valid in red (background-color) in the view

  • when a toast is displayed with the validation errors resume (something like: 'Save failed: affairNr is required' ) I would like to replace the property name with a more friendly name (something like 'Save failed: affair number is required')

Here is the portion code for the validation in the 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';
}

Does someone can point me in the right direction?

Thanks in advance.


EDIT:

To reproduce the problem: click on the left sidebar on Transports + recherche avancee + any item in the list + on the right side: clear some inputs (like Numero d'affaire as screenshot below) then click on 'Enregistrer'. Then the save button is called. There I need to check if there are invalid inputs with ko.validation.group but it doesn't work.


回答1:


Some time ago, I posted a helper function that extend observable properties to add validation based on the breeze validators. Using that helper you can achieve the red color on the invalid inputs:

Translate breeze validation messages

I can't help you with the second question, I know that you can customize the validation message but I think that with the default validators you can't set a friendly name to show on the message.

Update:

The first that I do is to create a helper module that exposes the function (updated version):

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
};
});

Then, I'm defining an initializer for each breeze entity type ( http://www.breezejs.com/documentation/extending-entities ). Example:

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

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

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

And finally, somewhere ( I'm doing it on an init function inside my dataservice module ), I'm registering the initializer ( 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);

I'm doing all of this before fetching the metadata.

I hope that this would help you.

Update 2:

I've found the problem, your version of knockout validation is not the last one.

Inside the downloaded file from: http://ericmbarnard.github.com/Knockout-Validation/ the line: 349 is:

exports.rules[ruleName] = ruleObj;

Inside your file, the equivalent line ( function addAnonymousRule ) is:

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

I think that with the lastest version should work.

Update 4:

This is the code to save:

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();
    }
});


来源:https://stackoverflow.com/questions/15635958/mark-fields-not-valid-as-red-with-knockout-durandal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!