Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify template in directive (dynamically adding another directive)

Problem

Dynamically add the ng-bind attribute through a custom directive to be able to use ng-bind, ng-bind-html or ng-bind-html-unsafe in a custom directive with out manually adding to the template definition everywhere.

Example

http://jsfiddle.net/nstuart/hUxp7/2/

Broken Directive

angular.module('app').directive('bindTest', [
'$compile',
function ($compile) {
    return {
        restrict: 'A',
        scope: true,
        compile: function (tElem, tAttrs) {
            if (!tElem.attr('ng-bind')) {
                tElem.attr('ng-bind', 'content');
                $compile(tElem)
            }
            return function (scope, elem, attrs) {
                console.log('Linking...');
                scope.content = "Content!";
            };
        }
    };
}]);

Solution

No idea. Really I can not figure out why something like the above fiddle doesn't work. Tried it with and with out the extra $compile in there.

Workaround

I can work around it might adding a template value in the directive, but that wraps the content in an extra div, and I would like to be able to that if possible. (See fiddle)

Second Workaround

See the fiddle here: http://jsfiddle.net/nstuart/hUxp7/4/ (as suggested by Dr. Ikarus below). I'm considering this a workaround for right now, because it still feels like you should be able to modify the template before you get to the linking function and the changes should be found/applied.

like image 919
nick.stuart Avatar asked Nov 17 '25 10:11

nick.stuart


2 Answers

You could do the compiling part inside the linking function, like this:

angular.module('app').directive('bindTest', ['$compile', function ($compile) {
    return {
        restrict: 'A',
        scope: true,
        link: {
            post: function(scope, element, attrs){
                if (!element.attr('ng-bind')) {
                    element.attr('ng-bind', 'content');
                    var compiledElement = $compile(element)(scope);
                }
                console.log('Linking...');
                scope.content = "Content!";                
            }
        }
    };
}]);

Let me know how well this worked for you http://jsfiddle.net/bPCFj/

like image 68
odiseo Avatar answered Nov 20 '25 00:11

odiseo


This way seems more elegant (no dependency with $compile) and appropriate to your case :

angular.module('app').directive('myCustomDirective', function () {
    return {
        restrict: 'A',
        scope: {},
        template: function(tElem, tAttrs) {
            return tAttrs['ng-bind'];
        },
        link: function (scope, elem) {
            scope.content = "Happy!";
        }
    };
});

jsFiddle : http://jsfiddle.net/hUxp7/8/

From Angular directive documentation : You can specify template as a string representing the template or as a function which takes two arguments tElement and tAttrs (described in the compile function api below) and returns a string value representing the template.

like image 20
Pierre Maoui Avatar answered Nov 20 '25 01:11

Pierre Maoui



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!