6

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?

2 Answers 2

11

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);
        }
    };
}]);
Sign up to request clarification or add additional context in comments.

2 Comments

Cleaner than my answer. I concede!
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?
1

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/

3 Comments

BTW - this works, but I have a feeling that there's a more elegant solution using priorities and transclude. Anyone?
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
That's more a jquery issue, check out stackoverflow.com/questions/247023/…

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.