Shai UI
Shai UI

Reputation: 51928

Nested ng-repeat with no nested divs?

I have an object that looks like:

var obj = [ 
[{x:3,y:3},{x:6,y:1},{x:3,y:5}],
[{x:1,y:3},{x:6,y:1},{x:3,y:5}],
[{x:3,y:3},{x:6,y:1},{x:3,y:5}]
]

Now I'd like to bind this in angular. But on the page I just want it to look like a bunch of divs (but with no nested div structures). So:

<div style='position:absolute; left:3px;top:3px'></div>
<div style='position:absolute; left:6px;top:1px'></div>
<div style='position:absolute; left:3px;top:5px'></div>
<div style='position:absolute; left:1px;top:3px'></div>
... and so on

But when I look at angular documentation it looks like I need to do:

<div ng-repeat="row in obj">
   <div ng-repeat="col in row">
   </div>
</div>

But this would created nested divs. Is there any way to create a flat div structure like I detailed above?

NOTE: Assume the data structure is as is (I can't create a flat list of objects)
^^^^^^

Upvotes: 2

Views: 678

Answers (4)

Fedaykin
Fedaykin

Reputation: 4552

Short answer: as it is, no you can´t do it without nesting your divs

To do that you must modify your array, flattening it on your controller and then bind to the flattened array. Here is a working plunker: http://plnkr.co/edit/KPHurN2XBkvwMW22X3MP?p=preview

Your HTML should be like this:

<div ng-repeat="item in flattenedObj" style="left:{{item.x}} top: {{item.y}}">X: {{item.x}} | Y: {{item.y}}</div>

Note that you can apply this flattening on your controller, but the recommended way is to use a service for that, you are probably receiving this array from an endpoint via $http, so treat it as you receive it.


UPDATE after reading that the structure should not be changed.

You can do this with directives, here is a working example:

http://plnkr.co/edit/Whf5YY8kV0zjEEM8vUAN?p=preview

app.directive('exampleDirective',[function(){
  return{
    restrict: 'E',
    replace: true,
    scope: {
      sub: '='
    },
    template: '<div></div>',
    link:function($scope, elem){
      var resultingHtml = '';

      for(var i=0; i<$scope.sub.length; i++){
        resultingHtml += '<div style="top: '+ $scope.sub[i].y +'px; left: '+ $scope.sub[i].x +'px;">X:' + $scope.sub[i].x + ' Y:' + $scope.sub[i].y + ' </div>';
      }

      elem.replaceWith(resultingHtml);
    }
  }
}]);

If you try to make it using a ng-repeat on the directive´s template, angular will try to use the upper scope because of the replace: true, so you must do it the hard way.

Hope that helps

Upvotes: 1

TheSharpieOne
TheSharpieOne

Reputation: 25726

Since you cannot change the shape of your data, you must assume it has certain properties, such as each inner array always contains 3 objects.

<div ng-repeat-start="row in obj" style='position:absolute; left:{{row[0].x}}px;top:{{row[0].y}};'></div>
<div style='position:absolute; left:{{row[1].x}}px;top:{{row[1].y}};'></div>
<div ng-repeat-end style='position:absolute; left:{{row[2].x}}px;top:{{row[2].y}};'></div>

Upvotes: 0

J-Dizzle
J-Dizzle

Reputation: 3191

Yeah, you've got this ng-repeat which iterates through the javscript objects in your array. Access those object properties. so check this one-line out.

<div ng-repeat="row in obj" style="{{ 'position:absolute; left:' +row.x + 'px;top:' + row.y +'px;'}}"></div>

... or

<div ng-repeat="row in obj" style="position:absolute; left:{{row.x}}px;top:{{row.y}}px;"></div>

Upvotes: 0

qwwqwwq
qwwqwwq

Reputation: 7309

If you want a flat list, flatten it in the controller before binding to scope. Flattening out a list shouldn't happen in your view.

Upvotes: 0

Related Questions