2

There is great solution provided for this question, that shows how to use a directive to display <tr>'s for nested objects. However, I need to take it a step further and pass a nested object into my attribute as well.

In the example below, I have added obj to my scope and the rows are now chained off obj. However, as soon as I do this it breaks and doesn't render any of the rows. What am I doing wrong?

My suspicion is it has to do with scope[attrs.rows] but I'm not positive.

HTML:

<div ng-controller="MyCtrl">
    <my-table rows='obj.rows'></my-table>
</div>

Javascript:

var myApp = angular.module('myApp', []);

myApp.directive('myTable', function () {
    return {
        restrict: 'E',
        link: function (scope, element, attrs) {
            var html = '<table>';
            angular.forEach(scope[attrs.rows], function (row, index) {
                html += '<tr><td>' + row.name + '</td></tr>';
                if ('subrows' in row) {
                    angular.forEach(row.subrows, function (subrow, index) {
                        html += '<tr><td>' + subrow.name + '</td></tr>';
                    })
                }
            })
            html += '</table>';
            element.replaceWith(html)
        }
    }
});

function MyCtrl($scope) {
    $scope.obj = {
        rows = [];
    }
    $scope.obj.rows = [
        { name: 'row1', subrows: [{ name: 'row1.1' }, { name: 'row1.2' }] },
        { name: 'row2' }
    ];
}

Here is my fiddle: http://jsfiddle.net/mattheye/uqNLH/1/

I'm trying to get it to work like this fiddle: http://jsfiddle.net/mrajcok/vGUsu/

Community
  • 1
  • 1
The Matt
  • 6,618
  • 7
  • 44
  • 61

1 Answers1

3

Instead of accessing the rows using scope[attrs.rows], use scope.$eval, like this:

angular.forEach(scope.$eval(attrs.rows), function (row, index) {

Working Demo


However, this will not update after you update rows on MainCtrl because the value is read only once.

To do the binding, you would want to set up a $watch on attrs.rows instead like this: http://jsfiddle.net/uqNLH/7/

musically_ut
  • 34,028
  • 8
  • 94
  • 106
  • Thanks, that's a great answer. The $watch, however, doesn't seem to fire when adding new obj.rows. Any ideas? http://jsfiddle.net/mattheye/uqNLH/4/ – The Matt Nov 21 '13 at 22:13
  • 1
    Ah, indeed. You need deep object watching to do that: http://jsfiddle.net/uqNLH/7/ In Angular 1.2, `$watchCollection` would suit your use case perfectly. However, `jsFiddle` does not allow me use it currently. – musically_ut Nov 21 '13 at 22:36