It's impossible to achieve this using only ng-repeat.
Your best bet is to incorporate a directive that automatically nests itself if it encounters a new child element.
I once created a custom directive for generating menus with an unknown number of sublevels. You can check it out here: http://plnkr.co/edit/8JL0Op?p=preview
Although I believe there may be more efficient ways to accomplish this (I developed this during my Angular learning phase), you might find some inspiration from this implementation.
Here's the code snippet:
angular.module('app', [])
.controller('Controller', ['$scope', '$timeout', function($scope, $timeout) {
$scope.name = "Test";
$scope.values = [
{"name":"test1"},
{"name":"test2", children:[
{"name":"test21"},
{"name":"test22"},
{"name":"test23", children:[
{"name":"test231"},
{"name":"test232"},
{"name":"test233"}
]}
]},
{"name":"test3"},
];
}]);
angular.module('app').directive('hyMenu', function($compile) {
return {
restrict: 'A',
scope:{
menuList:"=hyMenu"
},
link: function(scope, element, attrs) {},
templateUrl: function(element ,attrs) {
if(attrs.sub=="true"){
return 'hy-sub.htm';
} else {
return 'hy-menu.htm';
}
}
};
}).directive('hyElement', function($compile) {
return {
restrict: 'A',
scope: true,
link: function(scope, element, attrs, menuCtrl) {
if(!scope.elem.children){
scope.elem.children=[];
}
if (scope.elem.children.length > 0){
console.log(scope.elem.children);
element.append("<ul hy-menu='elem.children' data-sub='true'></ul>");
$compile(element.contents())(scope);
}
},
templateUrl: function(element, attrs) {
return 'hy-elem.htm';
}
};
});
Template files:
index.htm
<div class="hy-menu" hy-menu="values"></div>
hy-menu.htm
<ul>
<li ng-repeat="elem in menuList" hy-element="elem"></li>
</ul>
hy-sub.htm
<li ng-repeat="elem in menuList" hy-element="elem"></li>
hy-elem.htm
{{elem.name}}