user210757
user210757

Reputation: 7386

Breeze - Lazy Load Navigational Property

New to breeze - I have a breeze entity, that has an array navigational property in a one to many relationship. I'd like to check if the parent entity has any related child entities existing in the navigational property. This child array has not been expanded, and I'd like to lazy load for the check.

With the load happening asynchronously, it seems it may not be loaded by the check (if entity.children()...). It would seem I'd have the same issue if I put the check in the "then" callback. Is there a way to synchronously load the child array so that I can do the check and return whether populated or not? Or is there a better way to do this?

function doChildrenExist (entity) {

    var childrenExist = false;

    entity.entityAspect.loadNavigationProperty("children")
     .then(function () {})
     .fail(function () {});

    if(entity.children() !== null || entity.children().length > 0) {
        childrenExist = true;
    } 

    return childrenExist;
}

Upvotes: 3

Views: 1121

Answers (2)

PW Kad
PW Kad

Reputation: 14995

The reason this is not returning what you would like right now is because you are returning the childrenExist before the async query has completed. Putting the function inside your .then() will catch the call back, and only return IT'S callback once the data has been retrieved, unless it fails, in which case we can return an error or simply 'false'.

function doChildrenExist (entity) {

    var childrenExist = false;

    entity.entityAspect.loadNavigationProperty("children")
     .then(function () {
          if(entity.children().length > 0) {
              childrenExist = true;
          }
          return childrenExist; })
     .fail(catchError);

    function catchError(e) {
         alert(e.message);
         return false;
    }
}

to save a few bytes of code you should be able to do this as well -

function doChildrenExist (entity) {
    // No need to define a variable since we are either returning true or false
    entity.entityAspect.loadNavigationProperty("children")
     .then(function () {
          if(entity.children().length > 0) {
              return true;
          }
          return false; })
     .fail(catchError);

    function catchError(e) {
         alert(e.message);
         return false;
    }
}

and in your function that is calling doChildrenExist -

var showChildren = ko.observable(false);  // Do something like hide children until they exist

function refresh(entity) {
    doChildrenExist(entity)
         .then(checkResult)            
}

function checkResult(result) {
    showChildren(result);
}

Upvotes: 2

Jay Traband
Jay Traband

Reputation: 17052

There is no way to synchronously load a navigation property, ( this is the nature of ajax), but you are on the right track with the loadNavigationProperty. You could do something like the following where you pass in a callback function that will be called with either "true" or "false" depending on whether children exist.

function doChildrenExist(entity, callback) {

    entity.entityAspect.loadNavigationProperty("children").then(function () {
        // this syntax assumes knockout model library. 
        var childrenExist = entity.children().length > 0;
        callback(childrenExist);
    }).fail(function () {
        ...
    });
}

Upvotes: 3

Related Questions