I wonder what is the best practice when I have a response that has many different types of objects and looks like that:
[
{"nodeClass":"Entity", "text":"foo","entityfield":"booz"},
{"nodeClass":"User","username":"bar","userfield":"baz"}
]
and I have different templates for all of those:
for Entities:
<div class="{{nodeClass}} capsule">{{entity.text}}:{{entity.entityfield}}</div>
for Users:
<div class="{{nodeClass}} capsule">{{user.username}}:{{user.userfield}}</div>
how would you structure the code and with which angularjs elements (ng-repeat etc) to (re)use the correct templates based on the value of "nodeClass". Keep in mind that I don't want to make a new conditional template except if it is the only solution.
Edit: I have found those approaches: http://onehungrymind.com/angularjs-dynamic-templates/ and if else statement in AngularJS templates and Dynamically displaying template in ng-repeat directive in AngularJS? but they are quite different than my requirements. Especially the last one is the closest to what I want but my templates as usually have different variable names in them..
Thanks
One way is to use a 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
You can try pulling the template.html in the background via $http, parse the template and replace instances of the variable name that doesn't match your ng-repeat variable name. Then send that html from the template.html to a directive (or controller template) that has the ng-repeat in its template, insert the newly edited html via $('#elem').html(newHtml); and call $compile on the modified element.
The template you pull down could look like this
controller1/template1.html
<h1>{{item.data}} - {{item.name}}</h1>
Here is the template that the repeater sits in
controller1.html
<p>This is the view for controller 1.</p>
<div id="repeater" ng-repeat="thing in vm.items">
</div>
The fetching of the template, replacing of the desired string and re-compiling of the template can be done like this
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 working in action
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With