Hi everyone. In this article I want to show you how to render markdown content on your website or application from local .md files using ngx-markdown library with HttpClient service in Angular.
ngx-markdown
is an Angular library that combines:
- Marked to parse markdown to HTML
- Prism.js for language syntax highlight
- Emoji-Toolkit for emoji support
- KaTeX for math expression rendering
Intro
For the purpose of this blog post I will be using latest version of Angular, Angular 12. If you're using older versions of Angular, you can update your CLI and core version of framework with this command: ng update @angular/cli @angular/core
.
I highly recommend upgrading to Angular 12 as it is packed with new features, uses Ivy instead of View Engine and has increased performance at rendering and building your application.
You should also have basic understanding of Angular and Typescript for this blog post.
Setup
First, we need to create new Angular project. We can do that by running a command from @angular/cli
in an empty folder:
ng new markdown-render
By running this command it will promt some CLI options for you to choose.
I highly recommend adding angular routing in your project, and choose stylesheet format you prefer to use. After you chose project options, CLI will generate your project files and install npm modules.
Next we need to install ngx-markdown
library by running this command:
npm i ngx-markdown
Great! Now that basic project setup is done, we can create markdown renderer component.
Creating markdown rendered component
Add ngx-markdown and Http modules to application
First, as we installed ngx-markdown library, we will import it in our app.module.ts
file. We also need to import HttpClientModule
in the same file as it configures dependency injection for HttpClient
.
Our app.module.ts
should look like this:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { MarkdownModule } from 'ngx-markdown';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
MarkdownModule.forRoot(),
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Create markdown file
Now, add markdown file in your application. For the purpose of this blog post, create new folder in your src
folder called markdown-files
. Inside that folder create new file called markdown.md
and populate with some markdown content.
After that, we will add that folder to application assets so we can properly use the path to it with our HttpClient
.
To add markdown-files
folder to application assets, open your angular.json
file and add "src/markdown-files"
line of code inside assets
array.
"assets": [
"src/favicon.ico",
"src/assets",
"src/markdown-files"
],
Do that for both development and production environment.
Generate markdown component
Now that we imported modules in app.module.ts
, created markdown file and added it to application assets, it is time to finally create our component.
To generate new component we can use angular cli command:
// Long command
ng generate component components/markdown-preview
// Short command
ng g c components/markdown-preview
After we generate component we need to import HttpClient
and MarkdownService
,. Then we need to initialize them in out component constructor.
After import your component should look like this:
import { Component, OnInit } from '@angular/core';
import { MarkdownService } from 'ngx-markdown';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-markdown-preview',
templateUrl: './markdown-preview.component.html',
styleUrls: ['./markdown-preview.component.sass']
})
export class MarkdownPreviewComponent implements OnInit {
constructor(private mdService: MarkdownService, private http: HttpClient) { }
ngOnInit(): void { }
}
Now, let's add some code to fetch markdown file and render it on our page.
Inside our component class we will define a string variable that will store compiled raw markdown content. Add it inside component class, on the top:
markdown: string | undefined;
Then, inside async ngOnInit()
function we need too add 2 lines od code.
First, we need to get markdown file from our markdown-files
folder by using HttpClient
, convert response to type of text
and manage data as a promise by adding .toPromise()
at the end of a line.
const markdownRaw = await this.http.get('/markdown-files/markdown.md',
{ responseType: 'text' }).toPromise();
With that line we get raw markdown content which we need to compile into HTML to render it on our page.
To do that we finally use ngx-markdown
service to compile our markdown content.
this.markdown = this.mdService.compile(markdownRaw);
In the end, your markdown-preview.component.ts
file should look like this:
import { Component, OnInit } from '@angular/core';
import { MarkdownService } from 'ngx-markdown';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-markdown-preview',
templateUrl: './markdown-preview.component.html',
styleUrls: ['./markdown-preview.component.sass']
})
export class MarkdownPreviewComponent implements OnInit {
markdown: string | undefined;
constructor(private mdService: MarkdownService, private http: HttpClient) { }
async ngOnInit() {
const markdownRaw = await this.http.get('/markdown-files/markdown.md',
{ responseType: 'text' }).toPromise();
this.markdown = this.mdService.compile(markdownRaw);
}
}
To finally render it on our page, add this line to markdown-preview.component.ts
file:
<markdown [data]="markdown"></markdown>
<markdown>
tags comes from ngx-markdown
library and uses [data]
attribute to fetch compiled markdown content. In this case, "markdown"
inside [data]
is markdown
class property that we defined inside our class component and appended compiled raw markdown content to.
Add a route
Well, we are not yet done. We still need to add proper route to our markdown component.
Go to app-routing.module.ts
file and create a route for our markdown preview component:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { MarkdownPreviewComponent } from './components/markdown-preview/markdown-preview.component';
const routes: Routes = [
{
path: 'my-markdown',
component: MarkdownPreviewComponent
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Final touch
Finally, we need some basic navigation and router outlet in our app-component.html
file:
<section class="container">
<nav class="navigation">
<a routerLink="/my-markdown">OPEN MARKDOWN</a>
</nav>
<hr />
<router-outlet></router-outlet>
</section>
and some basic styles in app-component.sass
file:
.container
width: 70%
margin: 0 auto
.navigation
display: flex
justify-content: center
align-items: flex-start
a
text-decoration: none
color: #404040
font-size: 1.25rem
transition: 0.3s
&:hover
color: #0b4daf
And yes, I just centered anchor inside navigation with flexbox because I'm flexbox addict, I can't help myself :D
Now, after you completed everything, try running ng-serve
command and see it in action!
Conclusion
And that is it. Simple markdown renderer project with ngx-markdown
.
You can find project github repository here.
If you want to do more, check ngx-markdown docs for more information about the library.
I hope this is helpfull to you. If you have any feedback or any issues regarding code in this blog post, feel free to leave a comment, or reach me on discord.