1

I have a JSON file describing an x number of HTML elements and their content:

{
  "elements": [
    {
      "type" : "p",
      "content" : "Lorem Ipsum"
    },
    {
      "type" : "blockquote",
      "content" : "Lorem Ipsum",
      "by" : "Walter White"
    }
  ]
}

I have problem figuring out how to generate the described HTML elements on the view.

Am I approaching this in a completely wrong way? Those elements will compose a blog article.

I don't like to use markdown or directly save the HTML because I need every element to be editable from the front-end.

2
  • are you looking to only render the JSON content or incorporate two-way data binding so that you save any changes made in the frontend back to the JSON? Commented Aug 12, 2014 at 9:35
  • 1
    I don't need two-way binding, I can save all changes once the used finished the edit - the JSON is just a simplification, it will actually be a MongoDB object Commented Aug 12, 2014 at 9:37

3 Answers 3

2

Here is a Fiddle

I created a directive that can render HTML elements based on the data you've given. It's not yet refined but I think this will work.

angular.forEach(scope.elements, function(value, key) {
    // create an element based on its type
    var newElement = document.createElement(value.type);
    // add the content
    newElement.innerHTML = value.content;

    for (attribute in value) {
        if (attribute != 'type' && attribute != 'content') {
            //apply attribute
            newElement.setAttribute(attribute, value[attribute]);
        }
    }
    element.append(newElement);
});

Limitations

  • Nested elements are not handled by this code (further refinements can handle that)
  • This could be vulnerable to injection attacks, so I suggest you use the ngSanitize module or something similar
  • I'm not sure about the performance :)

This is to give you an idea that AngularJS can handle your concern.

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

Comments

1

Ok I came up with this solution, It's not elegant, but it works.

<div ng-repeat="element in elements">
  <div ng-if="element.type == 'p'">
    <p>{{element.content}}</p>
  </div>
  <div ng-if="element.type == 'blockquote'">
    <blockquote>
      {{element.content}}
      <span>by {{element.by}}</span>
     </blockquote>
  </div>
</div>

JsFiddle: http://jsfiddle.net/rdgda4pp/1/

Comments

0

Here is how I would proceed :

First of all you need to fetch the data inside a controller an expose them to the view using the $scope :

angular.module('app').controller('BlogCtrl', ['$scope', '$http', function($scope, $http){

$http({method: 'GET',url: '/blog/1/data'}).
        success(function (data) {
            if (data) {
                $scope.content = data;
            }
        })
      .error(function (error) {
          console.warn("Unable to retrieve data for this article");
      });

});

Inside your view, you would use your custom directive (we will come to it in a second) :

<div data-ng-controller="BlogCtrl">
  <dynamic-tag content="tag" ng-repeat="tag in content"></dynamic-tag >
</div>

Now, we have to tackle the most 'difficult' part : the directive. Our custom directive will generate the DOM elements according to your JSON definition.

angular.module('app').directive("dynamicTag",
            ['$document', '$compile', function($document, $compile) {

                var getTemplate = function(tag){
                    var template = '';
                    if (tag.type === 'p')
                     template += angular.element('<p>'+ tag.content + '</p>');
                    //Repeat and create elements for every tag you need to handle..

                    return template;
                }; 

                return {
                    restrict : 'E', 
                    replace: true,
                    scope: {
                        content:'=content'
                    },
                    link : function(scope, element, attrs) {                    
                        element.html(getTemplate(scope.content);
                        $compile(element.contents())(scope);
                    }
                };
            }]);

I have not tested my code, just wrote it from scratch. If you can't get it working, I can eventually make a plunker.

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.