1

In my web app, in a search result, each item can have a different look according to the type of item. To achieve this, I was thinking of including the layout with data placeholders for that particular item in the json response. How do I bind the scope data to the placeholders in the json response template?

for eg. My search result would look something like :

<li ng-repeat="item in items">
<div ng-bind-html="item.template"></div>
</li>

And the JSON response would look like :

[{
"template_name":"One",
"template":"<div ng-repeat='subitem in item.subitems'>{{subitem.name}}</div>",
"subitems":[{name:"John"},{name:"Jane"}]
},
{
"template_name":"Two",
"template":"<div ng-repeat='subitem in item.subitems'>{{subitem.name}}</div>",
"subitems":[{name:"John"},{name:"Jane"}]
}
]

Like you can see, I need to bind the placeholders in the json response with the scope data. Is there any way to do it? If not, how do you suggest i should address this situation?

Thank You!

aayush shrestha
  • 1,858
  • 2
  • 17
  • 33
  • Add the templates for the types via the template cache, then all your solution needs to know is that type X maps to template Y. Your JSON *data* responses don't need to have part in this. – Sacho Aug 21 '14 at 10:49
  • My templates need to be dynamically built in the server. That is why I couldnt opt for locally stored templates. – aayush shrestha Aug 21 '14 at 10:52
  • They need to be built *as you're fetching the data*? That doesn't make any sense. You can dynamically build them all you want, and then add them to the template cache - e.g. see http://stackoverflow.com/questions/12346690/is-there-a-way-to-make-angularjs-load-partials-in-the-beginning-and-not-at-when – Sacho Aug 21 '14 at 10:58
  • Well. yes. I know it sounds absurd. But here's the case. Its a search result page. Each result item could look different according to the type of the result item. So, there is no way of knowing which template to use until i read the individual item. That is why I decided to send the template data with the json response. – aayush shrestha Aug 21 '14 at 11:10

1 Answers1

1

While this will obviously not work:

<li ng-repeat="item in items">
  <div ng-bind-html="item.template"></div>
</li>

Since you are telling angular to display html that is inside item.template but what you really want is to tell it to treat item.template as it would be markup that should be parsed in a similar way to a template inside directive.

What you can do however is to define custom directive that will treat item.template in a desired manner. For instance:

<li ng-repeat="item in items">
  <div dynamic-template="item.template" />
</li>

Where dynamic-template is defined as follows:

 module.directive('dynamicTemplate', function($compile){
    return {
      scope: {
        dynamicTemplate:'='
      },
      replace:true,
      transclude: true,
      link: function($scope, $element, $attrs, _, $transcludeFn){
        // since we have isolate scope - transclude the element so it has access 
        // to item and anything else available inside ng-repeat
        $transcludeFn(function($childElement, $childScope){ 
          var link = $compile($scope.dynamicTemplate);
          var bound = link($childScope);
          $element.append(bound);
        });
      }
    };
  });

Of course this is not ideal since changes to item.template wont be reflected but you can easily extend this by adding $watch.

You can find working example here.

miensol
  • 39,733
  • 7
  • 116
  • 112
  • Hi. Thanks so much for the answer. It worked beautifully. However, I dont completely understand how this works. Can you please direct me to an article or something that covers this? – aayush shrestha Aug 26 '14 at 04:33