2

Given this data in my controller :

$scope.data = [
    {id: "1", ElementType: "paragraph", text: "some content"},
    {id: "2", ElementType: "listItem", text: "some list item content"},
    {id: "3", ElementType: "quote", text: "some quote"}
]

An given this ng-repeat in my view:

<div ng-repeat="item in data">{{item.text}}</div>

How can I render this HTML ? :

<p>Some content</p>
<ul>
    <li>some list item content</li>
</ul>
<blockquote>some quote</blockquote>

I've explored ng-switch but it keeps the parent div. In other words I want to replace the HTML produced by ng-repeat with new markup based on an object attribute.

Mike Cluck
  • 31,869
  • 13
  • 80
  • 91
PierreB
  • 1,947
  • 3
  • 16
  • 16
  • Try `ng-if` inside the `ng-repeat` directive? – Tony Aug 12 '14 at 17:42
  • Thanks Tony. I Tried ng-if. Like ng-switch it works but only for the markup inside the `
    – PierreB Aug 12 '14 at 17:51
  • You cannot get rid of the `
    ` element. Otherwise you won't be looping over anything. If you want to remove the parent post-render you could always use javascript to do DOM manipulation, but I don't understand why you'd want to do that.
    – Tony Aug 12 '14 at 17:56
  • I have to deal with a database with aweird structure that specifies the type of HTML element each content is supposed to use. I'd like to render the cleanest markup possible. Some HTML elements specified by the data are inline elements such as ``, so getting rid of the div is important for me. – PierreB Aug 12 '14 at 18:02

2 Answers2

1

just nest ng-if in <div ng-repeat=...>.

For else you can use ng-if with reversed condition

k0ner
  • 1,086
  • 7
  • 20
  • Interesting Koner. But I'm not sure I understand what you mean by "reversed condition". Can you please elaborate ? Can I get rid of the parent div that contains the ng-repeat directive ? – PierreB Aug 12 '14 at 17:57
  • ng-if="isType == true" and reversed condition ng-if="isType == false" – Darshan P Aug 12 '14 at 18:05
  • I mean the same what @dasu908 wrote – k0ner Aug 13 '14 at 08:41
1

You can do it inside a directive using the $compile angular function like shown in this plnkr.

UPDATE Here is a plnkr that works better

Here is the key part:

link: function (scope, ele, attrs) {
  scope.$watch(attrs.dynamic, function(html) {

    var htmlStr = '';
    var repeat = attrs.repeat;
    for(var i = 0; i< repeat; i++){
      htmlStr += html;
    }

    ele.html(htmlStr);
    $compile(ele.contents())(scope);
  });
}

Your controller would look like this:

function MyController($scope) {

$scope.html = '<p>{{id}}</p>\
              <ul>\
               <li>{{ElementType}}</li>\
              </ul>\
             <blockquote>{{text}}</blockquote>';
}

From your example, you'd remove the ng-repeat entirely and just use this directive. One change is that you'd pass in the whole $scope.data and dynamically pull out the bits you wanted to use in your html string. But because it's a string, that should be easy to do with simple string concatenation.

One final thing - you are probably going to have to put some tags in so you can replace your static content with dynamic data from your array. Kind of like ng-repeat! (but different all the same).

Finally, you could use interpolate to fill up your html string:

$interpolate(template)({
  id: id,
  ElementType: ElementType,
  text: text
});

Where you would get the data for these items from the controller

Caspar Harmer
  • 8,097
  • 2
  • 42
  • 39
  • Have you had any luck using this technique? – Caspar Harmer Aug 12 '14 at 19:27
  • Wow ! Looks like a great direction. Thanks ! Let me try to figure out exactly how to implement this (I'm learning Angularjs). Thanks a lot. – PierreB Aug 12 '14 at 19:43
  • CaspNZ, I can't see your addition in the plnkr. All i CAN see is the first code. – PierreB Aug 13 '14 at 09:51
  • Try this - it's all working for me in this plnkr: http://plnkr.co/edit/TUkSbc?p=preview (I've updated the answer plnkr to) – Caspar Harmer Aug 13 '14 at 17:39
  • With your solution in mind I did some more searching on similar custom ng-repeat solution and found this other [question](http://stackoverflow.com/questions/13651578/how-to-unwatch-an-expression), a very simple and elequent way to refactor ng-repeat for performance boost. Here's a [plunkr](http://plnkr.co/edit/ZJnLD3eS5wyyN7qq9UP9?p=preview) illustrating what I came up with based on this strategy – PierreB Aug 15 '14 at 14:07