Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am trying to create a highlight.js directive and I am having problems getting scope vars to apply.

<script src="http://code.jquery.com/jquery-1.8.2.min.js" ></script>
<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/default.min.css">
<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>

<div ng-app="app">
    <div ng-controller="MyCtrl">
        <snippet>&lt;script src=&quot;{{src}}&quot;&gt;&lt;/script&gt;</snippet>
        {{src}}
    </div>
</div>

function MyCtrl($scope) {
  $scope.src = "foo.js";   
}

app.directive('snippet', ['$timeout', function($timeout) {
    var template = '<pre><code></code></pre>';

    return {
        restrict: 'E',
        compile: function(tElement, tAttrs, transclude) {

            var rawCode = tElement.text();
            tElement.html(template);

            return function(scope, element, attrs) {
                $timeout(function() {
                    scope.$apply(function() {
                        var formattedCode = hljs.highlightAuto(rawCode);
                        $(element).find('code').html(formattedCode.value);
                    });
                }, 0);
            }
        }
    }
}]);​

Here is the fiddle: http://jsfiddle.net/dkrotts/RE7Jj/5/

As you can see, $scope.src is not applying its value inside the snippet. What am I doing wrong?

share|improve this question

2 Answers 2

The key is you should use $interpolate instead of $compile

Description of $interpolate

Compiles a string with markup into an interpolation function. This service is used by the HTML $compile service for data binding. See $interpolateProvider for configuring the interpolation markup.

When you use $complie, it will turn your string into element.

Description of $compile

Compiles a piece of HTML string or DOM into a template and produces a template function, which can then be used to link scope and the template together.

(To be honest, I don't really understand the description until trying it out.)

Here is the working plunk

app.controller('MainCtrl', function($scope) {
  $scope.cdnPath = "//path/to/cdn/";
  $scope.version = "1.0"; 
});

app.directive('snippet', ['$timeout', '$interpolate', function($timeout, $interpolate) {
    return {
        restrict: 'E',
        template:'<pre><code ng-transclude></code></pre>',
        replace:true,
        transclude:true,
        link:function(scope, elm, attrs){             
            var tmp =  $interpolate(elm.find('code').text())(scope);
             $timeout(function() {                
                elm.find('code').html(hljs.highlightAuto(tmp).value);
              }, 0);
        }
    };
}]);
share|improve this answer
1  
Cleaner than my answer. I concede! –  Roy Truelove Nov 16 '12 at 14:43
    
I'm finding if I have <p><snippet></snippet></p> with this code, I end up with <p></p><pre><code></code></pre> instead of the snippet remaining inside the <p> tag. Any ideas? –  Matt Williamson Aug 23 '13 at 15:21

You'll need to $compile the inner HTML. See the fiddle below. You also don't need to run w/in an $apply block.

app.directive('snippet', ['$timeout', '$compile', function($timeout, $compile) {
    var template = '<pre><code></code></pre>';

    return {
        restrict: 'E',
        compile: function(tElement, tAttrs, transclude) {

            var rawCode = tElement.text();
            tElement.html(template);

            return function(scope, element, attrs) {

                var g = $compile(rawCode)(scope);

                $timeout(function() {
                    var text = g[0].outerHTML;
                        var formattedCode = hljs.highlightAuto(text);
                        $(element).find('code').html(formattedCode.value);
                }, 0);
            }
        }
    }
    }]);​

http://jsfiddle.net/roytruelove/jMC9n/1/

share|improve this answer
1  
BTW - this works, but I have a feeling that there's a more elegant solution using priorities and transclude. Anyone? –  Roy Truelove Nov 14 '12 at 20:02
    
Thanks! It does work until I put something more complicated inside the <snippet> tag. Here is an updated fiddle that is breaking: jsfiddle.net/dkrotts/jMC9n/3 –  Dustin Nov 14 '12 at 20:29
    
That's more a jquery issue, check out stackoverflow.com/questions/247023/… –  Roy Truelove Nov 14 '12 at 21:33
    
no, it is not jquery issue. check out my answer. –  maxisam Nov 15 '12 at 20:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.