Ordering Breeze Navigation Collection on an Entity with AngularJs

倖福魔咒の 提交于 2019-12-13 05:04:28

问题


This is vary similar, Sorting Breeze navigation properties except I don't really understand the answer if it does apply. I posted for clarification.

I have a complex object called MasterTimeline

  • MasterTimeline
    • -Which has a collection of MasterPhases
      • Which has a collection of MasterMilestones. (side not Milestones also have a collection of Tasks with an order)

Here is json

    [
  {
    "$id": "1",
    "Id": 6,
    "Name": "New Construction",
    "MasterPhases": [
      {
        "$id": "2",
        "Id": 19,
        "Name": "Phase 1",
        "MasterTimelineId": 6,
        "Order": 1,
        "MasterMilestones": [
          {
            "$id": "3",
            "Id": 97,
            "Name": "Milestone 1",
            "MasterPhaseId": 19,
            "Order": 1,
            "MasterPhase": {
              "$ref": "2"
            }
          },
          {
            "$id": "6",
            "Id": 98,
            "Name": "Milestone 2",
            "MasterPhaseId": 19,
            "Order": 2,
            "MasterPhase": {
              "$ref": "2"
            }
      },
      {
        "$id": "11",
        "Id": 20,
        "Name": "Phase 2",
        "MasterTimelineId": 6,
        "Order": 2,
        "MasterMilestones": [
          {
            "$id": "12",
            "Id": 99,
            "Name": "Milestone 1",
            "MasterPhaseId": 20,
            "Order": 1,
            "MasterPhase": {
              "$ref": "11"
            }
          },
          {
            "$id": "17",
            "Id": 100,
            "Name": "Milestone 2",
            "MasterPhaseId": 20,
            "Order": 3,
            "MasterPhase": {
              "$ref": "11"
            }
          }
        "MasterTimeline": {
          "$ref": "1"
        }
      }
    ]
  }
]

Phases and Milestones both have a client configured Order property as they are part of a timeline and have to be set in the desired order. So here UI and the model overlap.

Using angular and breeze I get the timeline and loop through the phases.

  • ng-repeat=phase in timeline.phases
  • Then for each phases I loop through the milestones
    • ng-repeat=milestone in phase.milestones

Problem: The problem is I can't figure out how to order the phases or the milestones based on their order property. It seems just random. Even though in the API I've put an order on all the methods regarding these objects.

What I tried: What I did try was to use Breeze to get all Phases based on the timeline, then for each phase get the milestones, the code seemed to work but then I was getting angular errors that the uri was too long and chrome would just hang and fill the console up with errors about uri being too long.


Adding some Code as Requested: Note: All this works except I can order the Phases or Milestones

Web API Methods:

[BreezeQueryable(MaxExpansionDepth = 4)]
    [HttpGet]
    public IQueryable<MasterTimeline> MasterTimelines()
    {
        return _contextProvider.QueryAll<MasterTimeline>();
    }

    [BreezeQueryable(MaxExpansionDepth = 3)]
    [HttpGet]
    public IQueryable<MasterMilestone> MasterMilestones()
    {
        return _contextProvider.QueryAll<MasterMilestone>().OrderBy(x => x.MasterPhaseId).ThenBy(x => x.Order);
    }

    [HttpGet]
    public IQueryable<MasterMilestoneTask> MasterMilestoneTasks()
    {
        return _contextProvider.QueryAll<MasterMilestoneTask>().OrderBy(x => x.MasterMilestoneId).ThenBy(x => x.Order);
    }

    [HttpGet]
    public IQueryable<MasterPhase> MasterPhases()
    {
        return _contextProvider.QueryAll<MasterPhase>().OrderBy(x => x.Order);
    }

Angular MasterTimeline Repository with Breeze

function getTimelines() {
    var timelines = {};
    return EntityQuery.from(controllerMethodName)
                 .expand("masterPhases, masterPhases.masterMilestones, masterPhases.masterMilestones.masterMilestoneTasks")
                 //.orderBy(orderBy)
                 .using(self.manager).execute()
                 .then(querySucceeded, self._queryFailed);

function querySucceeded(data) {
                timelines = data.results;
                return timelines;
            }
}

Page Controller where I list Timelines (paraphrased)

    var vm = this;
    vm.timelines {}


 function activate() {
            var promises = [getItems()];
            common.activateController(promises, controllerId)
                .then(function () {
                    log('Activated Timeline View');
                });
        }

function getItems(forceRefresh) {
            return dc.mastertimeline.getTimelines()
                .then(
                    function (data) {
                        vm.timelines = data;
                        return data;
                    });
        };

activate();

Html on Page - I stripped it down as much as I could

<table>
                                <tbody>
                                    <tr data-ng-repeat="timeline in vm.timelines">
                                        <td>{{timeline.name}}</td>
                                        <td>
                                            <table>
                                                <thead>
                                                    <tr>
                                                        <th colspan="2">Phase(s)</th>
                                                    </tr>
                                                </thead>
                                                <tbody>
                                                    <tr data-ng-repeat="phase in vm.masterPhases">
                                                        <td><strong>{{phase.name}} (Order: {{phase.order}})</strong></td>
                                                        <td>
                                                            <table>
                                                                <thead>
                                                                    <tr>
                                                                        <th colspan="2">Milestone(s)</th>
                                                                    </tr>
                                                                </thead>
                                                                <tbody>
                                                                    <tr data-ng-repeat="milestone in phase.masterMilestones">
                                                                        <td>{{milestone.name}} (Order: {{milestone.order}})</td>
                                                                        <td>

                                                                        </td>
                                                                    </tr>
                                                                </tbody>
                                                            </table>
                                                        </td>
                                                    </tr>
                                                </tbody>
                                            </table>

                                        </td>
                                    </tr>
                                </tbody>
                            </table>

回答1:


The Answer:

Ignore everything below unless you can't use this solution, but was so simple as link (Zelda?) pointed out.

Other Solutions

Ok after days of trying different ways.

Found a solution that works.

Short version, after getting the data back from Breeze I pull out the child entity collections into their own js array and sort them. No idea why I can't just do this in the object itself, would make it so much easier.

<tr data-ng-repeat="timeline in vm.timelines">

1st Level Children Before:

    <tr data-ng-repeat="phase in vm.timeline.masterPhases">

function getItems(forceRefresh) {
                return dc.mastertimeline.getTimelines()
                    .then(
                        function (data) {
                            vm.timelines = data;
                            return data;
                        });
            };

1st Level Children After:

<tr data-ng-repeat="phase in vm.masterPhases">

function getItems(forceRefresh) {
                return dc.mastertimeline.getTimelines()
                    .then(
                        function (data) {
                            vm.timelines = data;
                            vm.masterPhases = vm.timelines[0].masterPhases;
                            vm.masterPhases.sort(function (a, b) { return a.order - b.order; });
                            return data;
                        });
            };

Then to get the sub-level of Milestones

2nd Level Children Before:

<tr data-ng-repeat="milestone in phase.masterMilestones">

2nd Level Children After:

<tr data-ng-repeat="milestone in vm.getMasterMilestones(phase.id)">

function getMasterMilestones(phaseId) {
            var phase = vm.masterPhases.filter(function(obj) {
                return (obj.id === phaseId);
            });
            var milestones = phase[0].masterMilestones;
            return milestones.sort(function(a, b) { return a.order - b.order; });
        }

Not sure if this is the best way but it works. Would be nice if BreezeJs could just allow sorting on the children navigation collections.


UPDATE: Even better solution Realized I didn't need to filter, I can just send in the child property right into the function.

<tr data-ng-repeat="timeline in vm.timelines">

1st Level

 <tr data-ng-repeat="phase in vm.getMasterPhases(timeline.masterPhases)">

function getMasterPhases(phases) {
            return phases.sort(function (a, b) { return a.order - b.order; });
        }

2nd Level

<tr data-ng-repeat="milestone in vm.getMasterMilestones(phase.masterMilestones)">

function getMasterMilestones(milestones) {
            return milestones.sort(function(a, b) { return a.order - b.order; });
        }



回答2:


Here's how to do it using an angularjs filter:

<tr data-ng-repeat="phase in vm.masterPhases | orderBy:'Order'">

<tr data-ng-repeat="milestone in phase.masterMilestones | orderBy:'Order'">

Reference:

https://docs.angularjs.org/api/ng/filter/orderBy



来源:https://stackoverflow.com/questions/24662696/ordering-breeze-navigation-collection-on-an-entity-with-angularjs

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