Search code examples
javascriptangulartypescriptbreezedevforce

Entity list by parent entity and dotted paths


I'm using Angular 5 + Breeze JS + breeze-bridge2-angular.

Suppose we have a Company entity that have multiple navigation properties of type Address and Address entity type, in its own turn, has some navigation properties like Country, etc:

import { Entity } from "breeze-client"; // From https://www.npmjs.com/package/breeze-client package 

export class Company implements Entity {
    billingAddress: Address;
    shippingAddress: Address;
}

export class Address implements Entity {
    country1: Country;
    country2: Country;
}

export class Country implements Entity {
    ...
}

All entities have been already queried into EntityMnager, no need to query anything from server.

How to implement a method (probably using some Breeze JS API I'm missing so far) taking a parent Company entity and a string[] of dotted property paths and returns a flat Entity[] list containing parent entity and all child entities located by using those dotted paths?

The dotted paths are just the same as we use with expand() method in Breeze queries (see Dotted expand paths here), i.e.:

const company: Company = ...; // Query Company and its children into EntityManager
const paths: string[] = [
    "billingAddress",
    "shippingAddress",
    "billingAddress.country1",
    "billingAddress.country2"];

getEntitiesFlat(entity: Entity, paths: string[]): Entity[] {
    // Not sure how to implement getChildren() method below
    const childEntities: Entity[] = this.getChildren(entity, paths);

    return [entity].concat(childEntities);
}

By the way, I'm trying to implement deletion of parent entity and its specific child entities and the above is the cleanest way I've came up so far inspired by DevForce framework. Better ideas are extremely welcomed.


Solution

  • not really sure what you're looking for. Assuming you're taking path and mapping those paths against the entity object... I came up with:

    function getByPath(entity: any, path: string) {
      if (!entity) return undefined
    
      const parts = path.split(".")
    
      if (parts.length === 1) {
        return entity[path]
      }
    
      return getByPath(entity[parts[0]], parts.slice(1).join("."))
    }
    

    use like

    const paths = ["a", "a.b.c", "a.b.d", "d", "c", "d.c"]
    const entity = {
      a: { b: { c: 1 } },
      b: 1,
      c: 2
    }
    
    paths.map(path => getByPath(entity, path)) // [ { b: { c: 1 } }, 1, undefined, undefined, 2, undefined ]
    

    edit: if you're using lodash already, just use lodash#get