Reputation: 285
Given an HTML template
<div class="info">
<div class="title"><a href="property-detail.html">{{title}}</a></div>
<div class="location">{{location}}</div>
<div class="property-info clearfix">
<div class="area"><i class="icon icon-normal-cursor-scale-up"></i>{{size}}<sup>2</sup></div>
<div class="bedrooms"><i class="icon icon-normal-bed"></i>{{bedrooms}}</div>
<div class="bathrooms"><i class="icon icon-normal-shower"></i>{{bathrooms}}</div>
</div><div class="price">{{price}}</div>
<div class="link">
<a href="{{details}}">View more</a>
</div>
</div>
And a model that fits this template (that is, has all the fields: title, location, price, etc.). I am looking for a way to programmatically bind the template to the model and then push the rendered results to an array. In pseudo-code I am looking to do something like that:
var boxes= [];
for (var i = 0; i < items.length; i++) {
var results = bind(template, items[i]);
boxes.push(results);
}
Where items is an array of items which i got from the database or any other source, and bind is basically the function that is responsible to populate the template with the model.
It makes sense to use a directive. Not sure how to do that though.
Any idea if and how it can be done using Angular?
Upvotes: 0
Views: 663
Reputation: 2305
Normally you never want to manipulate DOM in anything other than a directive. But why be dogmatic about it? If you really need a compiled template in a string format (for 3rd party widget consumption or such like) then you can put together a service similar to the following:
angular.module('app', []);
angular.module('app').controller('MainCtrl', function ($scope, templateCompiler) {
var boxes = [];
var data = [{
title: 'test',
location: 'location!',
size: 40,
bedrooms: 'yes',
bathrooms: 'uncertain',
price: 'if you have to ask...',
details: 'indeterminate'
},{
title: 'test2',
location: 'somewhere',
size: 'a woman never tells',
bedrooms: 3.14,
bathrooms: null,
price: 1400,
details: 'forthcoming'
}];
for (var i = 0; i < data.length; i++) {
var results = templateCompiler.bind(data[i]);
boxes.push(results);
}
$scope.boxes = boxes;
})
angular.module('app').service('templateCompiler', function ($compile, $templateCache, $rootScope) {
var service = {}
var template = $templateCache.get('boxTemplate');
var scope;
this.bind = function (data) {
scope = $rootScope.$new();
angular.extend(scope, data);
var link = $compile(template);
var content = link(scope);
scope.$apply();
return content.html();
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app='app'>
<script type="text/ng-template" id="boxTemplate">
<div class="info">
<div class="title"><a href="property-detail.html">{{title}}</a></div>
<div class="location">{{location}}</div>
<div class="property-info clearfix">
<div class="area"><i class="icon icon-normal-cursor-scale-up"></i>{{size}}<sup>2</sup></div>
<div class="bedrooms"><i class="icon icon-normal-bed"></i>{{bedrooms}}</div>
<div class="bathrooms"><i class="icon icon-normal-shower"></i>{{bathrooms}}</div>
</div><div class="price">{{price}}</div>
<div class="link">
<a href="{{details}}">View more</a>
</div>
</div></script>
<!-- TO PROVE YOU GET THE DESIRED OUTPUT -->
<div ng-controller="MainCtrl">{{boxes}}</div>
</div>
You also might consider wrapping your map widget in a directive.
Upvotes: 0