angular-highlightjs
angular-highlightjs copied to clipboard
Not working with dynamically pulled data
Hi, I have been trying to make this work for a while now.
First of all, content is a blog post, and it is a mixed content. So there are a few p
blocks, and then pre code
blocks. I have manipulated the data and placed hljs
directive to the code
tag, but it isn't working for me.
postSingleFactory.getPost($stateParams.url).then((data) => {
ctrl.post = data.data.post;
ctrl.post.comments.forEach(el => el.replyVisible = false);
ctrl.post.content = ctrl.post.content.replace('<pre class="language-markup">', '<pre>');
ctrl.post.content = ctrl.post.content.replace('<code>', '<code hljs hljs-language="js">');
console.log(ctrl.post.content);
})
ctrl.trustThis = (html)=>{
return $sce.trustAsHtml(html);
}
and here is how I am using it
<div class="single_post_content" ng-bind-html="sm.trustThis(sm.post.content)">
As i can see by inspecting my page that the code
block contains the two directives, but it isn't working. There are no errors, the css is loading properly too.
Why would this be happening?
According your description, you're actually required to have post.content
compiled by AngularJS again for directive (like hljs
) to work.
// In your controller, don't forget to inject `$templateCache`
$templateCache.put('postContent-xxx', ctrl.post.content);
<!-- use `ng-include` to render post content from `$templateCache` -->
<div class="single_post_content" ng-include="'postContent-xxx'"></div>
Another options is to write a new directive specialized for displaying post.content
's HTML code, as well as adding code highlightling with highlight.js
.
angular.module('myApp')
.directive('singlePostContent', function (hljsService, $window) {
return {
restrict: 'A',
link: function (scope, iElm, iAttrs) {
scope.$watch(iAttrs.singlePostContent, function (content) {
if (content) {
iElm.html(content);
// You don't even require angular-highlightjs for this
var service = $window.hljs || hljsService;
service.highlightBlock(iElm[0]);
}
else {
iElm.html('');
}
});
}
};
};
});
<div class="single_post_content" single-post-content="sm.post.content"></div>
Here's a working demo on Plunker: http://plnkr.co/edit/ZfB4tamhQIOLx0z9WUMH?p=preview
Hi, for some weird reason. the directive highlighted the whole content, even though the part that's not code
Try replacing the highlightBlock
call on <pre>
or <code>
elements.
var service = $window.hljs || hljsService;
service.highlightBlock(iElm.find('pre > code')[0]);
// or
service.highlightBlock(iElm.find('pre')[0]);
I've update the plunk with iElm.find('pre')[0]
, and it seems to work correctly now.
http://plnkr.co/edit/ZfB4tamhQIOLx0z9WUMH?p=preview
@pc035860 Hey, it still doesn't work. There was an issue from my end too. I write a post via TinyMCE editor, and when I write code with its inbuilt code tool, it adds an additional class to the pre
tag.
I removed that in the following manner:
ctrl.post.content = ctrl.post.content.replace(/<pre class="language-javascript">/g, '<pre>')
And then, it just styles the outer block. it isn't highlighting anything. So I inspected the element and found out that no language class has been added to my code
tag. So, I manually added javascript
, just to test things out, but it still didn't work.
What could be the reason for this?
Can you make a demo of your problem with plunker or something similar? I can't figure out why it's not working with current available information.
@pc035860 Hey, so I made it work with a few tweaks, one of them really bizarre to me. First, I stored the post's content in a scope variable and passed that to the directive, like this
ctrl.content = ctrl.post.content;
and then plugged that into the directive:
<div class="single_post_content" single-post-content="sm.content">
and it worked. I don't know why. The next issue was that it was only working for the first code block, so I changed it to this:
let codeBlocks = element.find('code');
let service = $window.hljs || hljsService;
for(let key in codeBlocks){
if(codeBlocks[key]){
service.highlightBlock(codeBlocks[key]);
}
}
And this works, but I get an error in the console
TypeError: e is undefined
Now, i can ignore that, but I really want to keep it clean.
Long story short, I made it work, but I don't know how.