1
votes

I have a use-case where I want to access whether or not ANY entities within my BreezeJS EntityManager has validation errors. Basically a "hasValidationErrors" on the EntityManager.

The use-case is simply that I want to disable a "Save changes" button on the UI, and since I am using the Angular Binding system it should be a fast operation.

To me, it seems that this does not exist, and am wondering if there are any simple workaround or any actual ways of accomplishing it.

The closest I've come is the following:

    var mgr = new breeze.EntityManager(
        {
            serviceName: "/breeze/Model/"
        });

    var errorCount = 0;
    mgr.validationErrorsChanged.subscribe(function (validationChangeArgs) {

        var added = validationChangeArgs.added;
        if (added) {
            errorCount += added.length;
        }

        var removed = validationChangeArgs.removed;
        if (removed) {
            errorCount -= removed.length;
        }
    });

And then using errorCount to see if there are any validation errors. But this approach does not take into consideration if an entity is detached when it has validation errors. (For example through a call to rejectChanges() on the EntityManager).

It also feels like a very "hackish" approach.

1
Have you checked the documentation on validation? breezejs.com/documentation/validation - PW Kad

1 Answers

0
votes

I don't believe there is a fast way to do this. It's such an unusual case that I rather doubt we'd implement special logic for this.

Detaching an entity does clear the validation errors. Have you confirmed that it doesn't raise the EM.validationErrorsChanged event? Bummer.

In any case, your approach does seem a bit brittle.

One way to short circuit the test is to check first if the EM has changes. If it doesn't, there is no point in checking for validation errors because you can only save changed entities (invalid unchanged entities don't matter).

Here's some code for your datacontext that might work for you (not tried or tested but the ideas are there):

datacontext.enableSave = em.hasChanges();      // should bind to datacontext.enableSave
datacontext.checkEnableSave = checkEnableSave; // can call at will
datacontext.suspendEnableSaveChecking = false  // as explained

// potentially reset flag when hasChanges changes
// or when validationErrorsChanged
em.hasChangesChanged.subscribe(checkEnableSave);
em.hasValidationErrorsChanged.subscribe(latchedCheckEnableSave );

function checkEnableSave () {

    datacontext.enableSave = em.hasChanges();
    if (!datacontext.enableSave) return; // no changes -> disable save

    // changes pending; only enable if no validation errors
    var changes = em.getChanges();
    for (var i = changes.length; i--;) {
        if (changes[i].entityAspect.hasValidationErrors) {
            datacontext.enableSave = false; // so sad
            return; // look no further;  we're done.
        }
    }        
}

// can disable validation error checking when you know
// that there will a flurry of validation changes
function latchedCheckEnableSave () {
    if (!dataContext.suspendEnableSaveChecking) {
        setEnableSave();
    }
}

As you can see, I was worried that the app might enter a phase of rapid validation checking which could trigger a perf killing cycle of validation error checks across many entities with pending changes. By offering a suspend toggle, the developer can put off the evaluation until a quiet time and then force the check

I'm not sure if you have to worry about $scope.$apply(). I'm pretty sure everything involved here is synchronous.