Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular: Selectively compile templates

I know that ng-non-bindable allows a given element and its children to be not compiled as a template. It seems it was designed to be peppered throughout a template as needed. Is there a way to tell Angular to not process a given element, BUT to "poke holes" into that and allow selected child elements to be processed? For example, I'd love to be able to do something like this:

<div ng-non-bindable>
    <div>{{2+2}}</div>
    <div ng-bindable>{{2+2}}</div>
</div>

And have it output:

{{2+2}}

4

I understand that ng-non-bindable wouldn't even allow ng-bindable to be processed, even if it existed. But does anything exist to allow an approach to templates like I've expressed?

To be more thorough, my ideal solution would not process anything Angular until if found the ng-bindable, not just the curly brace expressions. For example:

<div ng-non-bindable>
    <div ng-repeat="n in [1,2,3]">{{n+2}}</div>
    <div ng-bindable ng-repeat="n in [1,2,3]">{{n+2}}</div>
</div>

would result in:

{{n+2}}

3

4

5

like image 918
drukepple Avatar asked Jul 13 '15 20:07

drukepple


1 Answers

Custom nonBindable directive

You will not be able to use ngNonBindable (well, you could decorate it) like this due to how directive is configured. However it's pretty easy to write custom directive with this behavior:

app.directive('nonBindable', function($compile) {
    return {
        terminal: true, 
        priority: 999,
        compile: function(tElement) {
            return function(scope) {
                var bindable = tElement[0].querySelectorAll('[bindable]');
                [].forEach.call(bindable, function(el) {
                    $compile(el)(scope);
                });    
            };
        }
    };
});

and use it like this:

<div non-bindable>
    <div>{{2+2}}</div>
    <div bindable>{{2+2}}</div>
</div>

<br><br>

<div non-bindable>
    <div ng-repeat="n in [1,2,3]">{{n+2}}</div>
    <div bindable ng-repeat="n in [1,2,3]">{{n+2}}</div>
</div>

Demo: http://plnkr.co/edit/NEDP4WkBN4TlXdXKo8WI?p=preview

Decorate ngNonBindable

You can decorate original ngNonBindable directive like this:

app.config(function($provide) {
    $provide.decorator('ngNonBindableDirective', function($delegate, $compile) {
        var directive = $delegate[0];
        directive.compile = function(tElement) {
            return function(scope) {
                var bindable = tElement[0].querySelectorAll('[bindable]');
                [].forEach.call(bindable, function(el) {
                    $compile(el)(scope);
                });
            };
        };
        return $delegate;
    });
});

and use it this way:

<div ng-non-bindable>
    <div>{{2+2}}</div>
    <div bindable>{{2+2}}</div>
</div>

<br><br>

<div ng-non-bindable>
    <div ng-repeat="n in [1,2,3]">{{n+2}}</div>
    <div bindable ng-repeat="n in [1,2,3]">{{n+2}}</div>
</div>

Demo: http://plnkr.co/edit/HVczVkkQR88hC7191ep0?p=preview

like image 113
dfsq Avatar answered Oct 11 '22 04:10

dfsq