Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not working with dynamically pulled data #87

Open
relentless-coder opened this issue Sep 27, 2017 · 7 comments
Open

Not working with dynamically pulled data #87

relentless-coder opened this issue Sep 27, 2017 · 7 comments

Comments

@relentless-coder
Copy link

relentless-coder commented Sep 27, 2017

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?

@pc035860
Copy link
Owner

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

@relentless-coder
Copy link
Author

Hi, for some weird reason. the directive highlighted the whole content, even though the part that's not code

@pc035860
Copy link
Owner

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]);

@pc035860
Copy link
Owner

I've update the plunk with iElm.find('pre')[0], and it seems to work correctly now.

http://plnkr.co/edit/ZfB4tamhQIOLx0z9WUMH?p=preview

@relentless-coder
Copy link
Author

relentless-coder commented Sep 29, 2017

@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?

@pc035860
Copy link
Owner

pc035860 commented Oct 2, 2017

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.

@relentless-coder
Copy link
Author

relentless-coder commented Oct 2, 2017

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants