2016-11-19 3 views
2

Angular 2 앱에서 Highlight JS를 사용하려고하는데 코드 블록이 정적 정보가 아닌 경우이를 사용하는 방법을 알아 내는데 문제가 있습니다. 내 말은, 코드 문자열은 http get 호출을 통해 서버에서 오는 것입니다. 나는이있는 경우Angular 2에서 Highlight JS 사용

그래서 : 내가

success(data:any){ 
    this.submission = data; 
    this.criteria = data.criteria; 
    this.codeString = data.code; 
    hljs.highlightBlock(this.codeElement.nativeElement); 
} 

로 변경하는 경우, 그러나 아무 문제가 없습니다

export class WorkstationComponent implements OnInit { 

    private submission = new Submission(); 
    private criteria = new Array<ExerciseCriteria>(); 
    private codeString:string = ` 
     /* HelloWorld.java 
     */ 

     public class HelloWorld 
     { 
      public static void main(String[] args) { 
       System.out.println("Hello World!"); 
      } 
     }`; 

    constructor(private _router:Router, private submissionService:SubmissionService, 
       private activatedRoute:ActivatedRoute){} 

    @ViewChild('code') codeElement: ElementRef; 

ngOnInit(){ 
    this.activatedRoute.params 
     // (+) converts string 'id' to a number 
     .switchMap((params: Params) => this.submissionService.getSubmission(+params['id'])) 
     .subscribe(data => this.success(data), 
        error => this.fail(error)); 

} 

success(data:any){ 
    this.submission = data; 
    this.criteria = data.criteria; 
    hljs.highlightBlock(this.codeElement.nativeElement); 
} 

...

success

을 나는이를 얻을 수 :

fail

내가 뭘 잘못하고 있니? html로는 highlightBlock 평가됩니다 바인딩 codeString 전에 불을 받고, 같은

@PankajParkar 코멘트에서 언급 한 바와 같이
   <pre> 
        <code #code highlight class="java"> 
         {{codeString}} 
        </code> 
       </pre> 
+2

내 생각은'highlightBlock'는 codeString''전에 불을 받고있다 바인딩이 평가됩니다. 다음 틱을 기다리고'highlightBlock' 함수를 호출해야 할 수도 있습니다. 'hljs.highlightBlock (this.codeElement.nativeElement); 대신'setTimeout (>) => {hljs.highlightBlock (this.codeElement.nativeElement);}, 0);' –

답변

2

highlightBlock 기능은 내부 code 요소 컨텐츠 ISN 전에 불을 받고 있기 때문에이 일어나고있다 사용할 수 없습니다. 해결 방법 중 하나는 setTimeout이며 모든 바인딩이 적용되면 나중에 highlightBlock을 적용합니다. 그러나 불필요하게 다른 변경 감지를 실행하게됩니다.

내부 콘텐츠가 DOM에서 바운드되기를 기다리는 대신 DOM의 textContent에 수동으로 적용한 다음 highlightBlock 함수를 적용 할 수 있습니다.

Angular4에서

success(data:any){ 
    this.submission = data; 
    this.criteria = data.criteria; 
    this.codeString = data.code; 
    //making sure code is populated by below line 
    this.codeElement.nativeElement.textContent = data.code; 
    hljs.highlightBlock(this.codeElement.nativeElement); 
} 
+0

setTimeout 접근 방식이 저에게 효과적이었습니다 . "this.codeElement.nativeElement. 오류가 발생했습니다.두 번째 접근 방식으로 "textContent 함수가 아닙니다." –

+1

@ManuelZamith Ahh .. textContent는 메서드가 아닙니다 (실수로 메서드가 있습니다 :() .. 업데이트 된 대답 확인, 작동해야 함 :) –

+0

Brilliant :) 감사합니다. 너무 많이. –

-1

입니다.

Angler가 변경 감지 및 DOM 업데이트를 허용하므로이 기능을 다음 틱으로 실행하면 (setTimeout 사용) 작업이 지연됩니다.

대체 솔루션은 파이프를 사용하는 것입니다. 다음은 Prism.js을 사용하는 코드 하이라이트에 사용하는 파이프입니다. 당신은 쉽게 그것을 Highlight.js 사용하여 업데이트 할 수 있습니다

다음
@Pipe({ name: 'prism' }) 
export class PrismPipe implements PipeTransform { 
    constructor(private sanitizer: DomSanitizer) {} 
    transform(value, args) { 
    if (!isString(value)) { 
     throw new InvalidPipeArgumentException(PrismPipe, value); 
    } 
    let lang = args[0].toString().trim().toLowerCase(); 

    let grammar = Prism.languages[lang]; 
    // fallback to clike 
    if (!grammar) grammar = Prism.languages.clike; 
    return this.sanitizer.bypassSecurityTrustHtml(Prism.highlight(value, grammar)); 
    } 
} 

나는 다음과 같은 코드에서 사용 :

<pre [innerHtml]="codeString.source | prism:codeString.lang"></pre> 
0

는 구성 요소에서 highlight.js를 사용하는 코드 :

import {Component, ViewEncapsulation} from '@angular/core'; 
 
import * as hljs from 'highlight.js'; 
 

 
@Component({ 
 
    selector: 'cus-com', 
 
    template: ` 
 
    <pre> 
 
     <code [innerHtml]="html_content"></code> 
 
    </pre>`, 
 
    encapsulation: ViewEncapsulation.None, 
 
    styles: [require('highlight.js/styles/github.css')] 
 
}) 
 
export class CustomComponentsComponent { 
 
    languages = ['html', 'typescript']; 
 
    html_content = hljs.highlightAuto('<h1 class="big">Title</h1>', this.languages).value; 
 
}