我使用角度2创建简单的Web应用程序。我有两个组件。首先是基本上包含一些数据行的表。当执行单击行时,对应于行的数据显示在第二个组件中。数据是XML,加载到代码元素。它看起来像
@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 repo中的问题之后,我把它扔掉了。我接下来尝试的是基于这篇文章使用highlight.js创建指令:highlight.js does not work with Angular 2。使用此方法突出显示Xml,但仅单击第一次行。单击另一行时,甚至不显示新的xml。我也尝试使用prism.js,但我得到了相同的行为。一旦某个xml字符串第一次绑定,显示在代码元素中并使用highlight.js或prism.js突出显示,它仍然存在。
我的猜测是它与DOM和数据绑定在角度2中的工作方式有关,因为不使用语法高亮,我会在每次选择行时绑定并将字符串传递给代码元素。使用突出显示导致绑定字符串,将其传递给代码元素然后预先设置它。这意味着代码元素中没有简单的字符串,但是很多样式化的span元素,在选择新行时会导致加载新xml字符串的问题。我也试图绑定&#34; pre-prettified&#34;使用Prism.highlight(text_to_prettify)的字符串,但使用此方法会导致显示带有Prism添加的所有span元素的xml。
现在,我正在考虑如何解决这个问题。请给我一些推动,我怎么能让它发挥作用。
答案 0 :(得分:5)
你可以尝试我为Angular 2/4编写的这个简单angular-prism组件,因为ng2-prism不再被维护,并且不适用于最新的角度释放。
答案 1 :(得分:4)
我会创建一个利用prismjs的组件。
包括prismjs脚本,包括您需要的components文件夹中的任何脚本。
<强>的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>
为Prism安装最新的类型定义文件(这将为您提供类型安全性):
npm install @ryancavanaugh/prismjs
注意:不要安装@ types / prismjs - 它要么已过期,要么未正确创作。 prismjs
的作者推荐使用@ ryancvanaugh / prismjs作为类型定义。
将文件夹添加到typeRoots
中的tsconfig.json
列表属性中,以便typescript编译器可以找到它:
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]);
}
}
在app.module中声明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>
答案 2 :(得分:0)
我使用PixelBits解决方案,几乎没有任何更改,首先确保您不要在App.component.ts文件中尝试使用prism组件,在检查后,您会看到&#34; View已更改&# 34;如果您重新加载页面,则不会调用错误和ngAfterViewInit()。因此,制作一个基本的路由,一个页面,并在新页面中检查你的prism组件。 接下来,如果您想使用行号插件,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中)。