Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

245
Vistas
Syntax highlighting in Angular 2

I'm creating simple web app using angular 2. I have two components there. First is basically table with some data rows. When click on row is performed, data corresponding to row are displayed in the second component. Data are XML, loaded to code element. It looks something like

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

Everything worked fine until I wanted to add syntax highlighting for xml. First I wanted to use plugin ng2-prism, but I had problems to make it work correctly. After I saw issues in its git repo, I threw it away. What I tried next was to create directive using highlight.js based on this post: highlight.js does not work with Angular 2. Xml is highlighted using this method, but only the first time row is clicked. When another row is clicked, new xml is not even displayed. I also tried to use prism.js but I'm getting the same behavior. Once some xml string is first time binded, displayed in code element and highlighted using either highlight.js or prism.js, it remains.

My guess is it is related with how DOM and data binding works in angular 2, because without using syntax highlighting, I'm binding and passing string to code element every time row is selected. Using highlighting causes to bind string, pass it to code element and then pretiffy it. That means there is no simple string inside code element, but a lot of styled span elements, what causes problems to load new xml string when new row is selected. I also tried to bind "pre-prettified" string using Prism.highlight(text_to_prettify), but using this method causes to display xml with all of the span elements added by Prism.

Right now, I'm scratching my head thinking about how to solve this problem. Please give me some push how could I make it work.

about 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

I would create a component that leverages prismjs.

Include the prismjs scripts including any from the components folder that you need.

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>

Install the latest type definition files for Prism (this will give you type-safety):

npm install @ryancavanaugh/prismjs

Note: don't install @types/prismjs - its either out-of-date or not authored correctly. The author of prismjs recommends @ryancvanaugh/prismjs for the type definitions.

Add the folder to your typeRoots list property in tsconfig.json so that the typescript compiler can find it:

tsconfig.json (under compilerOptions)

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

Create a custom prism component that calls 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]);
     }
}

Declare the Prism component in app.module:

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 { }

Use it like this:

<prism language="csharp">
    var x = 3;
    class T
    {{ '{' }}
    {{ '}' }}
</prism>
about 4 years ago · Santiago Trujillo Denunciar

0

You can try this simple angular-prism component I wrote for Angular 2/4 since ng2-prism is no longer maintained and does not work for latest angular releases.

about 4 years ago · Santiago Trujillo Denunciar

0

I use PixelBits solution, with few changes, first make sure you don't try the prism component in the App.component.ts file, you would get a "View changed after it has been checked" error and ngAfterViewInit() would not be called if you reload the page. So make a basic routing, and a page and trys your prism component inside that new page. Next if you want to use line-number plugin, Prism.highlight won't work. You need to use Prism.highlightElement. Also with PixelBits solution you get empty space before and after your code. Don't forget to change reference path url so it match your project.

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

and 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>

Also i don't use npm to get prism.js, but i took it from the official prism website (plugin for line-number is integrated inside prism.js).

about 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda