2017-04-01 127 views
2

我使用角度2創建簡單的Web應用程序。我在那裏有兩個組件。首先是基本上有一些數據行的表。當點擊行時,第二個組件顯示與行對應的數據。數據是XML,加載到代碼元素。它看起來像Angular 2中的語法高亮

@Component 
export class TableComponent { 
    items: Data[]; 
    selectedItemsXml: string; 
    ...other stuff 

    //when row is clicked 
    toggleSelectedRow(rowIndex: number) { 
     ...other stuff related to change row's background color 
     this.selectedItemsXml = this.items[i].xml; 
    } 
    ...other stuff again 
} 

//TableComponent's template 
<div> 
    <table> 
     ... 
     ...*ngFor="let item of items; let i = index;"... 
     <tr (click)="toggleSelectedRow(i)"> 
      <td>{{item.id}}</td> 
      <td>{{item.time}}</td> 
     </tr> 
     ... 
    </table> 
</div> 
<xml-detail [xml]="selectedItemsXml"></xml-detail> 

@Component 
export class XmlDetailComponent { 
    @Input() xml: string; 
} 

//XmlDetailComponent's template 
<div> 
    <pre><code>{{xml}}</code></pre> 
</div> 

一切工作正常,直到我想爲XML添加語法高亮。首先,我想使用插件ng2-prism,但是我遇到了問題以使其正常工作。在我看到它的git回購問題後,我把它扔掉了。我接下來嘗試的是基於這篇文章使用highlight.js創建指令:highlight.js does not work with Angular 2。使用此方法突出顯示Xml,但僅單擊第一次行。當單擊另一行時,甚至不會顯示新的xml。我也嘗試使用prism.js,但我得到相同的行爲。一旦某個xml字符串首次綁定,顯示在代碼元素中並使用highlight.js或prism.js突出顯示,它仍然存在。

我的猜測是它與角度2中DOM和數據綁定的工作方式有關,因爲如果沒有使用語法高亮顯示,我會在每次選擇行時綁定並將字符串傳遞給代碼元素。使用突出顯示會導致綁定字符串,將其傳遞給代碼元素,然後將其重新提交。這意味着在代碼元素內部沒有簡單的字符串,但是有很多樣式化的span元素,當選擇新行時,導致加載新的xml字符串時出現問題。我還嘗試使用Prism.highlight(text_to_prettify)綁定「pre-prettified」字符串,但使用此方法會導致顯示帶有由Prism添加的所有span元素的xml。

現在,我正在思考如何解決這個問題。請給我一些推動我怎麼能使它工作。

+0

我不確定你的意思是「當選擇新行時加載新的xml字符串」。你能澄清這個問題嗎? – pixelbits

+0

你好,我添加了縮短的代碼示例。也許現在更清楚了。 –

回答

3

我會創建一個利用prismjs的組件。

包含prismjs腳本,包括您需要的任何組件文件夾。

的Index.html

<link href="node_modules/prismjs/themes/prism.css" rel="stylesheet" /> 
<script src="node_modules/prismjs/prism.js"></script> 
<script src="node_modules/prismjs/components/prism-core.js"></script> 
<script src="node_modules/prismjs/components/prism-clike.js"></script> 
<script src="node_modules/prismjs/components/prism-csharp.js"></script> 

安裝了棱鏡最新類型定義文件(這會給你的類型安全):

npm install @ryancavanaugh/prismjs 

注意:不要安裝@類型/ prismjs - 它或者過時或者沒有正確創作。作者prismjs建議@ ryancvanaugh/prismjs用於類型定義。

的文件夾添加到您的typeRoots列表屬性在tsconfig.json使得打字稿編譯器可以找到它:

tsconfig.json(compilerOptions下)

"typeRoots": [ 
    "node_modules/@types", 
    "node_modules/@ryancavanaugh" 
] 

創建一個自定義prism組件調用Prism.highlight

prism.component.ts

/// <reference path="../node_modules/@ryancavanaugh/prismjs/prism.d.ts" /> 
import { 
    Component, 
    AfterViewInit, 
    Input, 
    ElementRef, 
    ViewChild 
} from '@angular/core'; 

@Component({ 
    moduleId: module.id, 
    selector: 'prism', 
    template: ` 
     <div hidden="true" #rawContent> 
      <ng-content></ng-content> 
     </div> 
     <pre> 
      <code [innerHTML]="content"> 
      </code> 
     </pre> 

    ` 
}) 
export class PrismComponent implements AfterViewInit { 
    @Input() language: string; 
    @ViewChild("rawContent") rawContent: ElementRef; 
    content: string; 

    constructor(private elementRef:ElementRef) { 
    } 

    ngAfterViewInit() { 
     this.content = Prism.highlight(this.rawContent.nativeElement.innerHTML, Prism.languages[this.language]); 
    } 
} 

在應用程序中聲明Prism組件。模塊:

app.module.ts

import { NgModule } from '@angular/core'; 
import { BrowserModule } from '@angular/platform-browser'; 
import { HttpModule } from '@angular/http'; 

import { AppComponent } from './app.component'; 
import { PrismComponent } from './prism.component'; 

@NgModule({ 
    imports: [ 
     BrowserModule, 
     HttpModule   
     ], 
    declarations: [AppComponent, PrismComponent], 
    providers: [/* TODO: Providers go here */], 
    bootstrap: [AppComponent], 
}) 
export class AppModule { } 

使用方法如下:

<prism language="csharp"> 
    var x = 3; 
    class T 
    {{ '{' }} 
    {{ '}' }} 
</prism> 
+0

我能夠用這個答案和下面的@Vaibhav提供的回購的組合來處理事情。謝謝大家! –

2

你可以試試這個簡單的angular-prism組件我因爲ng2-prism寫了角2/4是沒有維護時間更長,不適用於最新的角度版本。

+0

角棱鏡爲我工作得很好。我花了很多時間製作我自己的作品,這樣好多了。 – rjdkolb

+0

謝謝!使用您製作的和原始棱鏡源,我編寫了一個版本,可以在打字稿/ Angular 2/4中生成,而無需導入任何單獨的,香草JavaScript庫。它只是一個服務,一個組件,以及任何用於語法主題的CSS,打包成一個NgModule。我從來沒有向Github貢獻過任何東西,所以我對這個工作原理很無知。我應該創建一個全新的回購並將其作爲單獨的東西上傳嗎?或者我應該向你的貢獻,看看你是否可以納入它? – diopside

+0

@diopside您可以使用其中一個Yeoman生成器來創建Angular庫包。一旦它工作,將代碼推到一個git倉庫,你也可以在npm上發佈你的模塊。所有這些步驟都可以輕鬆找到互聯網上的指南 –

0

我使用PixelBits解決方案,只做了很少的更改,首先確保不要嘗試App.component.ts文件中的prism組件,您將得到一個「查看已更改後已檢查」錯誤,並且ngAfterViewInit( )如果您重新加載頁面,則不會被調用。所以做一個基本的路由和一個頁面,並在您的新頁面中查找您的棱鏡組件。 接下來,如果您想使用行號插件,Prism.highlight將不起作用。您需要使用Prism.highlightElement。 此外,藉助PixelBits解決方案,您可以在代碼之前和之後獲得空白空間。 不要忘記更改引用路徑網址,使其與您的項目相匹配。

TS:

export class PrismComponent implements OnInit,AfterViewInit { 
    @Input() language: string; 
    @ViewChild("rawContent") rawContent: ElementRef; 
    @ViewChild("codeRef") codeRef: ElementRef; 
    content: string; 
    myClass:string; 

    constructor(
     private elementRef:ElementRef, 
    ) { 
    } 

    ngOnInit(){ 
     this.myClass = "language-" + this.language; 
    } 

    ngAfterViewInit() { 
     // trim because ng-content add space 
     this.content = this.rawContent.nativeElement.innerHTML.trim(); 
     // make line number plugin work. 
     Prism.highlightElement(this.codeRef.nativeElement,true); 
    } 
} 

和HTML:

<pre class="line-numbers"><code #codeRef [innerHTML]="content" [class]="myClass"></code></pre> 
<div style="display: none;" hidden="true" #rawContent> 
    <ng-content></ng-content> 
</div> 

而且我不使用NPM來獲得prism.js,但我把它從官方網站棱鏡(插件線 - 數字在prism.js中集成)。