4

Does Angular have a way to return to me an HTML string when given a template and an object to apply it to?

Angular has a powerful templating engine which I'd like to utilize it to generate HTML that can be copied out of my web app from an textbox, (or similar) and pasted into an external CMS.

Example:

Input object

var friends = [
    {name:"Steve",age:32,favoriteFood:"Pizza"},
    {name:"Maria",age:28,favoriteFood:"Pasta"},
    {name:"Susan",age:30,favoriteFood:"Burritos"}
]

Template

<h1>Friends</h1>
<ul>
<li ng-repeat="friend in friends">
    <div>
        {{friend.name}} is {{friend.age}} years old and likes to eat
        <strong>{{friend.favoriteFood | lowercase }}</strong>.
    </div>
</li>
</ul>

Output/Copyable HTML

<h1>Friends</h1>
<ul>
<li ng-repeat="friend in friends">
    <div>
        Steve is 32 years old and likes to eat
        <strong>pizza</strong>.
    </div>
</li>
<li ng-repeat="friend in friends">
    <div>
        Maria is 28 years old and likes to eat
        <strong>pasta</strong>.
    </div>
</li>
<li ng-repeat="friend in friends">
    <div>
        Susan is 30 years old and likes to eat
        <strong>burritos</strong>.
    </div>
</li>
</ul>
1

1 Answer 1

6

You can use pass in $compile to do directive-processing at will and then snatch up the angular-generated html to do whatever you want with it. But you also need to supply a unique scope based on the user's model input to the new element, and you can do that with $rootScope.$new(). In my example, the model format is expected to be JSON, so that it doesn't like, explode, but if you're making this for your own personal use you could allow regular js input and use eval(), allowing the user to write a more sophisticated model.

Here it is in action: http://jsbin.com/inocag/4/

JS

var module = angular.module('module', []);
module.directive('xxAngulizer', function($compile, $rootScope) {
  return {
    restrict: 'A',
    template: '<div>TEMPLATE</div><textarea id="template" ng-model="template" ng-change="update"></textarea>' +
      '<div>MODEL</div><textarea id="model" ng-model="model" ng-change="update"></textarea>' +
      '<div>HTML OUTPUT</div><textarea id="output" ng-model="output"></textarea>' +
    '<div id="hidden" ng-hide="true"></div>',
    scope: true,
    link: function($scope, elem) {
      var templateElem = $(elem.find('#template'));
      var modelElem = $(elem.find('#model'));
      var outputElem = $(elem.find('#output'));
      var hiddenElem = $(elem.find('#hidden'));

      $scope.template = '<div ng-repeat="cat in cats">{{cat.name}} the famous {{cat.breed}}</div>';
      $scope.model = '{ "cats": [{ "name": "Fussy", "breed": "Russian Blue" },' +
        ' { "name": "Juniper", "breed": "Maine Coon" },' +
        ' { "name": "Chives", "breed": "Domestic Shorthair" }] }';
      $scope.output = '';
      $scope.update = update;

      var $magicScope;

      function update() {
        var model, template;
        try {
          model = JSON.parse($scope.model);
        } catch (err) {
          model = null;
          $scope.output = 'Model is not valid JSON.';
        }
        if (model) {
          try {
            template = $($scope.template);
          } catch (err) {
            console.log(err);
            template = null;
            $scope.output = 'Template is not valid(ish) HTML.';
          }
        }
        if (template) {
          if ($magicScope) { $magicScope.$destroy(); }
          $magicScope = $rootScope.$new(true);
          for (var p in model) {
            $magicScope[p] = model[p];
          }
          //$scope.$apply(function() {
            $compile(hiddenElem.html(template))($magicScope);
          //});
          //$scope.$apply(function(){
          //  $scope.output = hiddenElem.html();
          //});
          setTimeout(function(){
            $scope.output = hiddenElem.html();
            $scope.$apply();
          }, 500);
        }
      }

      $scope.$watch('template', update);
      $scope.$watch('model', update);
      setTimeout(update, 500);
    }
  };
});

HTML

<!DOCTYPE html>
    <html>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script>
<body ng-app="module">
  <div xx-angulizer></div>
</body>
</html>

This was fun, I actually learned quite a bit in the process of answering!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.