Tyll'a
Tyll'a

Reputation: 551

How to dynamically render a markdown file in Angular?

I'm trying to write an Angular component that renders markdown files as part of the webpage, using the ngx-markdown library. Looking at the library's official demo, it has a list of files that it requires, which are then rendered from:

From the demo's app.component.ts:

  blockquotes = require('raw-loader!./markdown/blockquotes.md');
  codeAndSynthaxHighlighting = require('raw-loader!./markdown/code-and-synthax-highlighting.md');
  emphasis = require('raw-loader!./markdown/emphasis.md');
  headers = require('raw-loader!./markdown/headers.md');
  horizontalRule = require('raw-loader!./markdown/horizontal-rule.md');
  images = require('raw-loader!./markdown/images.md');
  links = require('raw-loader!./markdown/links.md');
  lists = require('raw-loader!./markdown/lists.md');
  listsDot = require('raw-loader!./markdown/lists-dot.md');
  tables = require('raw-loader!./markdown/tables.md');

And from the demo's app.component.html:

<!-- HEADER -->
<section id="headers">
<h2 class="subtitle">Headers</h2>

<pre>{{ headers }}</pre>

<markdown>{{ headers }}</markdown>
</section>

There are other sections that read from the other requires, but the syntax is the same.

What I'm trying to do is to have a method that changes which file the <markdown> tag reads from. Here's what I have so far:

  // Markdown variable.
  markdown;

  ngOnInit() {
    this.setMarkdown('home.md');
  }

  setMarkdown(file: string) {
    const path = 'raw-loader!./assets/markdown/' + file;
    this.markdown = require(path);
  }

I'm obviously doing something wrong, since I get a compiler error:

ERROR in src/app/app.component.ts(24,21): error TS2591: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.

What am I doing wrong, and how would I go about writing a method that changes the markdown source and actually works?

Upvotes: 19

Views: 31344

Answers (3)

penleychan
penleychan

Reputation: 5470

Based on the documentation here, you can load file via [src]:

<!-- loaded from remote url -->
<div markdown [src]="'path/to/file.md'" (load)="onLoad($event)" (error)="onError($event)"></div>

Upvotes: 12

Hameed Syed
Hameed Syed

Reputation: 4215

After lot of trials and errors, there is one more approach for dynamic rendering of markdown using ngx-markdown package via http calls.

Use HttpClient to make http call for md files:

import { HttpClient } from '@angular/common/http';
import { MarkdownService } from 'ngx-markdown';

export class AppComponent {
  title = 'personal-blog';
  markdownRaw ='';
  markdown='';
  
  constructor(private mdService:MarkdownService, private 
 httpClient:HttpClient){ }

  async ngOnInit() {
    this.markdownRaw = await this._httpClient.get(`/assets/hello.md`, 
    {
      responseType: 'text'
    }).toPromise();
        
    this.markdown=this.mdService.compile(this.markdownRaw);
  }
    
  onLoad(data:any) {
    console.log(data);
  }
         
  onError(data:any){
    console.log(data);
  }
}

Now use the declared and initialized variable as data property in markdown directive:

<markdown [data]="markdown" (load)="onLoad($event)" (error)="onError($event)"></markdown>

Upvotes: 3

Royer Adames
Royer Adames

Reputation: 1076

In general, you can load md files as string with the HTTP client

async ngOnInit() {
    this.md = await this.http.get(`/assets/posts/1.md`, 
                    { responseType: 'text'}).toPromise();
}

Live editor example

https://stackblitz.com/edit/angular-reading-markdown-in-global-assets?embed=1&file=src/app/app.component.ts

Source

https://fireflysemantics.medium.com/loading-markdown-files-with-the-angular-httpclient-155e31acab68

Upvotes: 0

Related Questions