1

How can one utilize a string contained within a variable as a template?

For example:

Controller

$scope.items = [
    {
         name: "Bruce Wayne"
    },
    {
         name: "Lucius Fox"
    }
];
$scope.template = "<input ng-model='item.name' type='text'>";

View

<div ng-repeat="item in items">
    <div ng-bind-html="<!-- The `template` variable defined in the controller. -->">
    </div>
</div>

I've tried $sce.trustAsHtml, which only doesn't connect with the actual scope when using things like ng-model='item.name'. Reading through the $sce docs I don't think that it provides anything that can trust a string as a template.

A fiddle for you to play with.

5
  • have you tried using a $rootScope instead? or declaring your template in a setTimeout(function(){}, 0) ? Commented Feb 20, 2017 at 18:25
  • @Nicolas In my case the template is loaded dynamically from a database, so it's already wrapped in an asynchronous callback and no, this doesn't change anything. Assigning to $rootScope would still have the item accessible in the $scope, just defined in a parent instead. I don't believe that would change anything. Commented Feb 20, 2017 at 18:27
  • You should use a directive for things like that. Directives can have it's own scope and controller (among other things), so they are perfect for this. For he html binding itself you can use $sce.trustAsHtml, like you said Commented Feb 20, 2017 at 18:27
  • If the template is loaded dinamically from the database, you can use templateProvider for the directive's template. Commented Feb 20, 2017 at 18:28
  • @FranePoljak It is loaded from a database, but it's stored in a JSON encoded array, so I don't think I can fetch it by itself from the database, nor do I want to. I really need to take a string and parse it into a template. As to the directive, I've thought and tested a bit of that as well. Take a look at this and tell me if it's what you were thinking. Commented Feb 20, 2017 at 18:46

1 Answer 1

2

to actually bind data from ng repeat to input need to compile the html. for that this directive can be used

app.directive('dynamic', function($compile) {
    return {
        restrict: 'A',
        replace: true,
        link: function (scope, element, attrs) {
            scope.$watch(attrs.dynamic, function(html) {
                element[0].innerHTML = html;
                $compile(element.contents())(scope);
            });
        }
    };
});

<div ng-repeat="item in items">
   <div dynamic="template">
   </div>
</div>

$scope.items = [
    {
         name: "Bruce Wayne"
    },
    {
         name: "Lucius Fox"
    }
];
$scope.template = "<input ng-bind='item.name' type='text'>"; 

Demo

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

5 Comments

Like this? I've already tried that.
isnt it bad form to change the type of template like that?
@sachilaranawaka So, this works as is, but, unfortunately, causes major problems when using the template variable within the array. See this. If you look at console you'll see the infinite digest.
@brhardwick well it depend on the situation also. it take additional resource and time to compile html manually. But if you need data to bind to html from some service this is the way
@sachilaranawaka Nevermind. This is correct. It's the $sce.trustAsHtml that's throwing all the errors. You don't need any trustAsHtml when $complileing. Recommend updating answer to remove that, but check this and it works.

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.