1

I'd like to use a configuration object to display a list. The problem is that this list has different types of elements it can contain: item, divider, and subheader.

A simple configuration for this list might be:

var list = [
    "item",
    "item",
    "divider",
    "subheader",
    "item",
    "item"
];

How do I write an ngRepeat attribute that would output something like this:

<md-menu-content>
    <md-menu-item>...</md-menu-item>
    <md-menu-item>...</md-menu-item>
    <md-menu-divider></md-menu-divider>
    <md-subheader>...</md-subheader>
    <md-menu-item>...</md-menu-item>
    <md-menu-item>...</md-menu-item>
</md-menu-content>

I'm not even sure this is possible. Looking at the documentation for ngRepeat, it can only be used as an attribute, so something like <ng-repeat>...</ng-repeat> is not an option. md-menu-item, md-menu-divider, and md-subheader also have to be elements as they're part of Angular Material and even if list item and the subheader aren't specifically restricted to being an element (unlike the divider), their CSS styles are written to be for elements only.

I've also played around with ngRepeatStart, but that's an alternative to ngRepeat, and they, as far as I can see, cannot be used together so that ngRepeat would be one level above ngRepeatStart.

gligoran
  • 3,267
  • 3
  • 32
  • 47

2 Answers2

0

Using the directive from this answer, you can do something like the following:

$scope.list = [
  "item",
  "item",
  "divider",
  "subheader",
  "item",
  "item"
];
$scope.attrs = [];
for(var i = 0; i < $scope.list.length; i++){
    $scope.attrs.push([{attr: 'md-menu-' + $scope.list[i], value: ''}]);
}

html:

<div ng-repeat="item in attrs" dyn-attr="item">
    something
</div>

See this jsfiddle

Of course you can tweak this however you want. The directive of the linked answer adds attributes based on a list, but you'll probably want to create a directive that just uses something like dyn-md-attr="item"

Community
  • 1
  • 1
devqon
  • 13,818
  • 2
  • 30
  • 45
0

Using the answer by @devqon I have a partial solution to this problem that works, but generates a lot of unnecessary digests that need to be dealt with. Nevertheless, it creates dynamic element with a directive that replaces the current element.

The fiddle is here: http://jsfiddle.net/qk96y2rw/

Here's the code:

myApp.directive('dynAttr', function() {
    return {
        scope: { list: '=dynAttr' },
        link: function(scope, elem, attrs){
        //console.log(scope.list);
            for(attr in scope.list){
                if (scope.list[attr].attr) {
                console.log(scope.list[attr].attr);
                var replacementElement = document.createElement(scope.list[attr].attr);
                 replacementElement.innerHTML = elem.html();
                 elem.replaceWith(replacementElement);

                }
            }
        }
    };
});
nixkuroi
  • 2,259
  • 1
  • 19
  • 25