Question

Here is my plunk: http://plnkr.co/edit/BGD0n6gmDM3kv5akIn4l?p=info

I am trying to make a view factory of sort. Ideally my controller will place a config object into scope that the view will use to render the page. It will be used to build navigation and content. I am stuck while trying to dynamically pass directives/partial view references from this object.

Here is a isolated object from the config in my controller:

$scope.partials = [
    {
        name: 'Well',
        method: 'showWell()',
        isVisible: false,
        template: '<container-well></container-well>'
    }
 ];

The focus of this question would be the template property. I built directives to function as partial views here.

Here is an example of one of my directives:

myApp.directive('containerWell', function() {
    return {
        restrict: 'E',
        replace: false,
        templateUrl: 'containers/well.html',
        scope: {}
    }
});

And here is the well.html template file:

<div>
    <h2 class="special">Well Types</h2>
    <div class="well well-cc">
        <p>Closed Well</p>
        <p>CSS: .well.well-cc</p>
    </div>

    <div class="well well-cc open">
        <p>Open Well</p>
        <p>CSS: .well.well-cc.open</p>
    </div>

    <h3 class="alt">Wells can have different highlights applied with css classes</h3>
    <div class="well well-cc highlight-warning">
        <p>CSS: .well.well-cc.highlight-warning</p>
    </div>
</div>

Here is the code in my view that I am failing with:

<div ng-repeat="partial in partials" ng-bind-html-unsafe="{{partial.template}}"></div>

The generated markup looks like this:

<div class="ng-scope" ng-bind-html-unsafe="<container-well></container-well>" ng-repeat="partial in partials"></div>

Its just basically adding the string tag to the attribute instead of the directive.

Basically, I would like to be able to programatically add directives to my view. I am not sure if what I am trying to do is even possible. I am not confident that passing the string equivalent of the directive is the way to go. I would love some suggestions or even some stern correction if I am being ridiculous; well not too stern, maybe something constructive ;)

Here is my plunk: http://plnkr.co/edit/BGD0n6gmDM3kv5akIn4l?p=info

Thanks,

Jordan

Was it helpful?

Solution

You have to $compile the dynamic template. See the example in the docs. I forked your plunk to demonstrate the case:

http://plnkr.co/edit/WBT9FbZmvp0Xj0LAAPzk?p=preview

The points are:

  • ng-bind-html-unsafe is unsuitable for this usage.
  • Create another directive to compile the dynamic template, just as in the example:

Compilation is actually quite easy:

MyApp.directive("myDir", function($compile) {
    return {
        link: function(scope, elem, attrs) {
            scope.$watch(
                function(scope) {
                    return scope.$eval(attrs.myDir);
                },
                function(value) {
                    var e = $compile(value)(scope);
                    elem.contents().remove();
                    elem.append(e);
                }
            );
        }
    };
});

Use it as:

<div ng-repeat="partial in partials">
    <div my-dir="partial.template"></div>
</div>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top