How to render mixed json results for different templates (with different variables) using angularjs

I wonder what is best when I have an answer that has many different object types and looks like this:

[
{"nodeClass":"Entity", "text":"foo","entityfield":"booz"},
{"nodeClass":"User","username":"bar","userfield":"baz"}
]

      

and I have different templates for everyone:

for objects:

<div class="{{nodeClass}} capsule">{{entity.text}}:{{entity.entityfield}}</div>

      

for users:

<div class="{{nodeClass}} capsule">{{user.username}}:{{user.userfield}}</div>

      

how would you structure your code and which corner element (ng-repeat, etc.) on (re) use the correct templates based on the "nodeClass" value. Keep in mind that I don't want to create a new conditional template, except that this is the only solution.

Edit: I found these approaches: http://onehungrymind.com/angularjs-dynamic-templates/ and if else statement in AngularJS templates and Dynamic template rendering in ng-repeat directive in AngularJS? but they are very different from my requirements. Especially the last one is closest to what I want, but my templates tend to have different variable names in them.

thank

+3


source to share


4 answers


You can try pulling template.html

in the background with $http

, parse the pattern, and replace instances of the variable name that doesn't match your variable name ng-repeat

. Then send this html

from template.html

in a directive (or controller template) that has ng-repeat

in your template, insert the newly edited html through $('#elem').html(newHtml);

and call $compile

on the changed element.

The template you are pulling might look like this:

controller1/template1.html

<h1>{{item.data}} - {{item.name}}</h1>

      

Here is the pattern where the repeater is in

controller1.html



<p>This is the view for controller 1.</p>

<div id="repeater" ng-repeat="thing in vm.items">

</div>

      

Extracting the template, replacing the desired string, and recompiling the template can be done as follows:

controller1.js

function Controller1($scope, $http) {
    var vm = this;

    vm.items = [{name: 'item1', data: 123}, {name: 'item2', data: 456}];

    var templateReplacement = '{{thing.';
    $http.get('controller1/template1.html')
        .then(function success(response) {
            var newHtml = response.data.replace(/{{item./g, templateReplacement);
            var repeaterElem = $('#repeater');

            $(repeaterElem[0]).html(newHtml);

            $compile(repeaterElem)($scope);
    }, function failure(reason) {
            console.log(reason);
    });
}

      

Here is a plunk of this action in action

+2


source


One way is to use dynamically generated ng-include

url

Html

  <div ng-repeat="item in data">
    <div ng-include="getContentUrl(item.nodeClass)"></div>
  </div>

      

Templates



  <script type="text/ng-template" id="partials/Entity.html">
    <h3>Entity Template , text= {{item.text}}</h3>
  </script>
  <script type="text/ng-template" id="partials/User.html">
    <h3>User Template , username ={{item.username}}</h3>
  </script>

      

Js

app.controller('MainCtrl', function($scope) {
  $scope.data=[{"nodeClass":"Entity", "text":"foo"},{"nodeClass":"User","username":"bar"}];
  $scope.getContentUrl = function(nodeClass){
    return 'partials/'+nodeClass +'.html';
  }
});

      

DEMO

+4


source


I built a directive that takes two attributes, one for the template and the other for whatever data you need to pass to the template.

Pass the value of the template selector using a switch statement, which will then apply the correct template and sort your data accordingly. Plunker

Directive

app.directive('templateSelector', function($compile) {
  return {
    restrict: 'A',
    scope: {},
    link: function(scope, el, attr) {
      console.log(attr.tClass, attr.tVals)
      var template ='';
      scope.data = angular.fromJson(attr.tVals);
      switch (attr.tClass) {
        case 'Entity':
          template = '<div><h1>Entity Class Template</h1>{{data.text}}</div><hr/>';
          break;
        case 'User':
          template = '<div><h1>User Class Template</h1>{{data.username}}</div><hr/>';
          break;
      }
      $template = angular.element(template);
      $compile($template)(scope);
      el.append($template); 
    }  
  }
})

      

HTML:

<div ng-repeat="d in dataset">
    <div template-selector t-class="{{d.nodeClass}}" t-vals="{{d}}"></div>      
</div>

      

+1


source


I can change data from the service before it ever reaches the view. This works with ng-if to determine which HTML to display:

<div ng-repeat="data in dataset">
  <div
    class="capsule"
    ng-class="data.nodeClass"
    ng-bind="data.text"
    ng-if="data.nodeClass==='Entity'"></div>
  <div
    class="capsule"
    ng-class="data.nodeClass"
    ng-bind="data.username"
    ng-if="data.nodeClass==='User'"></div>
</div>

      

Plunger fork made of tpie

+1


source







All Articles