Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angularjs: ng-repeat with different html tags

Say one have a list of multiple type of data defined in a controller as follows:

$scope.list = [
    {text: "Remember BASIC?"},
    {code: "10   a = a+1"},
    // many additional lines…
];

Which we want to interpolate in the view depending on each individual type as follows:

<p>Remember BASIC?</p>
<code>10   a = a+1</code>

How would you do that?

[edit] Clarification about what to obtain

List is a descriptionof an arbitrary number of "paragraph" of arbitrary types. Here is an more extensive list:

$scope.list = [
    {text: "Remember BASIC?"},
    {code: "10   a = a+1"},
    {text: "Bla bla"},
    {text: "Bla bla"},
    {text: "Bla bla"},
    {text: "Bla bla"},
    {text: "Bla bla"},
    {text: "Bla bla"},
    {code: "20   b = a+1"},
    {code: "30   c = b+1"},
    {text: "Bla bla"},
    // many additional lines…
];

And the expected result:

<p>Remember BASIC?</p>
<code>10   a = a+1</code>
<p>Bla bla</p>
<p>Bla bla</p>
<p>Bla bla</p>
<p>Bla bla</p>
<p>Bla bla</p>
<p>Bla bla</p>
<code>20   b = a+1</code>
<code>30   c = b+1</code>

etc.

It's not an issue to have an englobing tag, but I don't want an englobing tag for every single "paragraph".

like image 312
Stéphane de Luca Avatar asked Jun 22 '26 13:06

Stéphane de Luca


2 Answers

I'm not 100% sure what do you mean by

// many additional lines…

but if your list looks like

$scope.list = [   

       {text: "Remember BASIC?"},
       {code: "10   a = a+1"},
       {text: "Remember Loundy?"},
       {code: "10   a = a+3"}  
   ....
  ];

you can use ng-repeat-start /end

please see here http://jsbin.com/zawige/3/edit

  <p ng-repeat-start="i in list" ng-if="i.text">{{i.text}}</p>
  <code ng-repeat-end ng-if="i.code">{{i.code}}</code>
like image 77
sylwester Avatar answered Jun 25 '26 23:06

sylwester


Yes you can do this with a directive that loads a dynamic template:

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

function getTemplate(type) {
    if(type === 'text') {
        return '<p>{{item.contents}}</p>';
    }
    else if(type === 'code') {
        return '<pre>{{item.contents}}</pre>';
    }

    return '{{item.contents}}';
}

myApp.directive("customListItem", function($compile) {
    return {
        restrict: 'E',
        scope: {
            item: '='
        },
        link: function($scope, $element) {
            $element.html(getTemplate($scope.item.type));
            $compile($element.contents())($scope);
        }
    };
});


function MyCtrl($scope) {
    $scope.list = [
        {type: 'text', contents: "Remember BASIC?"},
        {type: 'code', contents: "10   a = a+1"}
    ];
}

You could probably write that ng-repeat so that you can use your original list structure. The key here is $element.html that injects the correct template into the original and $compile that interprets the bindings in it. Note that the original custom-list-item element will still be present in the DOM. No way you can eliminate that with ng-repeat.

Here it is in action.

like image 41
Sergiu Paraschiv Avatar answered Jun 25 '26 23:06

Sergiu Paraschiv