Вложенные ng-repeat

У меня есть фиктивный XML файл:

<Week number="2013-W45">
    <Day dow="1" templateDay="Monday">
        <Job name="wake up" >
            <Job name="get dressed" >
                <Job name="prepare breakfast" >
                    <Job name="eat breakfast" > </Job>
                </Job>
            </Job>
        </Job>
        <Job name="work 9-5" >
        </Job>
    </Day>
    <Day dow="2" templateDay="Tuesday"   >
        <Job name="wake up" >
            <Job name="get dressed" >
                <Job name="prepare breakfast" >
                    <Job name="eat breakfast" > </Job>
                </Job>
            </Job>
        </Job>
        <Job name="work 9-5" >
        </Job>
        <Job name="football" >
        </Job>
    </Day>
    <Day dow="3"   templateDay="Wednesday" >
        <Job name="wake up" >
            <Job name="get dressed" >
                <Job name="prepare breakfast" >
                    <Job name="eat breakfast" > </Job>
                </Job>
            </Job>
        </Job>
        <Job name="work 9-5" >
        </Job>
    </Day>
    <Day dow="4"  templateDay="Thursday"  >
        <Job name="wake up" >
            <Job name="get dressed" >
                <Job name="prepare breakfast" >
                    <Job name="eat breakfast" > </Job>
                </Job>
            </Job>
        </Job>
        <Job name="work 9-5" >
        </Job>
        <Job name="football" >
        </Job>
    </Day>
    <Day dow="5" templateDay="Friday" >
        <Job name="go to pub" >
        </Job>
    </Day>
    <Day dow="6" templateDay="Saturday"  >
        <Job name="work 9-5" >
        </Job>
    </Day>
    <Day dow="7" templateDay="Sunday" >
        <!-- nothing to do on sunday -->
    </Day>
</Week>

Используя эту библиотеку http://code.google.com/p/x2js/, я конвертирую ее в json, в переменную myData

 {
    "Week" : {
        "Day" : [{
                "Job" : [{
                        "Job" : {
                            "Job" : {
                                "Job" : {
                                    "_name" : "eat breakfast"
                                },
                                "_name" : "prepare breakfast"
                            },
                            "_name" : "get dressed"
                        },
                        "_name" : "wake up"
                    }, {
                        "_name" : "work 9-5"
                    }
                ],
                "_dow" : "1",
                "_templateDay" : "Monday"
            }, {
                "Job" : [{
                        "Job" : {
                            "Job" : {
                                "Job" : {
                                    "_name" : "eat breakfast"
                                },
                                "_name" : "prepare breakfast"
                            },
                            "_name" : "get dressed"
                        },
                        "_name" : "wake up"
                    }, {
                        "_name" : "work 9-5"
                    }, {
                        "_name" : "football"
                    }
                ],
                "_dow" : "2",
                "_templateDay" : "Tuesday"
            }, {
                "Job" : [{
                        "Job" : {
                            "Job" : {
                                "Job" : {
                                    "_name" : "eat breakfast"
                                },
                                "_name" : "prepare breakfast"
                            },
                            "_name" : "get dressed"
                        },
                        "_name" : "wake up"
                    }, {
                        "_name" : "work 9-5"
                    }
                ],
                "_dow" : "3",
                "_templateDay" : "Wednesday"
            }, {
                "Job" : [{
                        "Job" : {
                            "Job" : {
                                "Job" : {
                                    "_name" : "eat breakfast"
                                },
                                "_name" : "prepare breakfast"
                            },
                            "_name" : "get dressed"
                        },
                        "_name" : "wake up"
                    }, {
                        "_name" : "work 9-5"
                    }, {
                        "_name" : "football"
                    }
                ],
                "_dow" : "4",
                "_templateDay" : "Thursday"
            }, {
                "Job" : {
                    "_name" : "go to pub"
                },
                "_dow" : "5",
                "_templateDay" : "Friday"
            }, {
                "Job" : {
                    "_name" : "work 9-5"
                },
                "_dow" : "6",
                "_templateDay" : "Saturday"
            }, {
                "_dow" : "7",
                "_templateDay" : "Sunday"
            }
        ],
        "_number" : "2013-W45"
    }
}

У дня может быть любое количество заданий, задания могут быть вложенными и содержать любое количество других заданий.

Теперь, используя этот код

<p ng-repeat="day in myData.Week.Day">
   {{day._dow}} - {{day._templateDay}}
</p>

Я могу перечислить дни, которые работают. Я бы ожидал, что со следующим кодом

<p ng-repeat="day in myData.Week.Day">
    {{day._dow}} - {{day._templateDay}}

    <span ng-repeat="job in day.Job">
        {{job._name}}
    <span/>
</p>

Я могу перечислить дни и рабочие места верхнего уровня для этого дня, но это не сработает. (Перечислить вложенные Джобсы будет следующая задача, а не спрашивать об этом сейчас).

Итак, как перечислить как минимум рабочие места верхнего уровня? Также в json-формате я вижу, что некоторые вакансии Objects, а некоторые - Arrays. Как обрабатывать обе ситуации?

PS: использование angular 1.2.0-rc.3

Ответ 1

Лучше иметь правильный формат JSON вместо прямого использования конвертированного из XML.

[
  {
    "number": "2013-W45",
    "days": [
      {
        "dow": "1",
        "templateDay": "Monday",
        "jobs": [
          {
            "name": "Wakeup",
            "jobs": [
              {
                "name": "prepare breakfast",

              }
            ]
          },
          {
            "name": "work 9-5",

          }
        ]
      },
      {
        "dow": "2",
        "templateDay": "Tuesday",
        "jobs": [
          {
            "name": "Wakeup",
            "jobs": [
              {
                "name": "prepare breakfast",

              }
            ]
          }
        ]
      }
    ]
  }
]

Это упростит и упростит работу.

Теперь вы можете написать цикл как -

<div ng-repeat="week in myData">
   <div ng-repeat="day in week.days">
      {{day.dow}} - {{day.templateDay}}
      <b>Jobs:</b><br/> 
       <ul>
         <li ng-repeat="job in day.jobs"> 
           {{job.name}} 
         </li>
       </ul>
   </div>
</div>

Ответ 2

Если у вас большой вложенный объект JSON и его использование на нескольких экранах, вы можете столкнуться с проблемами производительности при загрузке страницы. Я всегда использую небольшие индивидуальные объекты JSON и запрашиваю связанные объекты как ленивую загрузку только там, где они требуются.

вы можете достичь этого, используя ng-init

<td class="lectureClass" ng-repeat="s in sessions" ng-init='presenters=getPresenters(s.id)'>
      {{s.name}}
      <div class="presenterClass" ng-repeat="p in presenters">
          {{p.name}}
      </div>
</td> 

Код на стороне контроллера должен выглядеть ниже

$scope.getPresenters = function(id) {
    return SessionPresenters.get({id: id});
};

Хотя API factory выглядит следующим образом:

angular.module('tryme3App').factory('SessionPresenters', function ($resource, DateUtils) {

        return $resource('api/session.Presenters/:id', {}, {
            'query': { method: 'GET', isArray: true},
            'get': {
                method: 'GET', isArray: true
            },
            'update': { method:'PUT' }
        });
    });

Ответ 3

Создайте фиктивный тег, который не будет отображаться на странице, но он будет работать как держатель для ng-repeat:

<dummyTag ng-repeat="featureItem in item.features">{{featureItem.feature}}</br> </dummyTag>