I am running Angular 6 with RxJs 6.
I am trying to get the value out of paramMap and assign it to a property. The route looks like this:
{
path: 'post/:postName',
component: PostComponent
}
The post component currently looks like this:
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';
import { switchMap } from 'rxjs/operators';
import { Observable, of } from 'rxjs';
import * as matter from 'yaml-front-matter';
import { Post } from '../../models/post';
@Component({
selector: 'blog-post',
templateUrl: './post.component.html',
styleUrls: ['./post.component.css'],
encapsulation: ViewEncapsulation.Emulated
})
export class PostComponent implements OnInit {
created: Date;
postName = '';
markdown = '';
title = '';
loading = true;
author = '';
constructor(private route: ActivatedRoute) { }
async ngOnInit () {
this.route.paramMap.pipe(
switchMap((params: ParamMap) =>
of(params.get('postName'))
)
).subscribe(d => this.postName = d);
const file = await fetch(`/_posts/${this.postName}.md`);
const text = await file.text();
const content = text.trim();
this.parseFrontMatter(content);
}
parseFrontMatter (content: string) {
const frontMatter: Post = matter.loadFront(content);
this.title = frontMatter.title;
this.author = frontMatter.author;
this.created = frontMatter.created;
this.markdown = frontMatter.__content;
this.loading = false;
}
}
In the ngOnInit is the code for getting the value out of the paramMap. This code works unless you try to route back to the post component with a different parameter.
This can be observed at Devbin.io.
The full source can be found on GitHub
All of the documentation and other Stack Overflow answers always assume you want to call a service in the switchMap function. The official documentation is here
My question is how do I get the route parameter and assign it to a property and keep navigation working while navigating back to the same route?
This is because ngOnInit doesn't get called when you route to the same component. In your case /post/Angular-6-Router-How-To-Get-Route-Parameters and /post/About are triggering the same component: post.component.
So to make this work you could call a function inside subscribe in paramMap.pipe.
You can do something like this:
ngOnInit() {
this.route.paramMap.pipe(
switchMap((params: ParamMap) =>
of(params.get('postName'))
)
).subscribe((d) => {
this.postName = d;
this.postInit();
});
}
async postInit() {
const file = await fetch(`/_posts/${this.postName}.md`);
const text = await file.text();
const content = text.trim();
this.parseFrontMatter(content);
}
parseFrontMatter(content: string) {
const frontMatter: Post = matter.loadFront(content);
this.title = frontMatter.title;
this.author = frontMatter.author;
this.created = frontMatter.created;
this.markdown = frontMatter.__content;
this.loading = false;
}
So I have cloned the repo and fixed the issue.
Replace this:
async ngOnInit () {
this.route.paramMap.pipe(
switchMap((params: ParamMap) =>
of(params.get('postName'))
)
).subscribe(d => this.postName = d);
const file = await fetch(`/_posts/${this.postName}.md`);
const text = await file.text();
const content = text.trim();
this.parseFrontMatter(content);
}
with the following:
ngOnInit() {
this.route.paramMap.pipe(
switchMap((params: ParamMap) =>
of(params.get('postName'))
)
).subscribe(d => {
this.postName = d;
fetch(`/_posts/${this.postName}.md`)
.then(data => data.text()
.then(text => {
const content = text.trim();
this.parseFrontMatter(content);
}));
});
}
Explanation: You were fetching the posts only when the component was initialized since your file fetch code was outside of the Observable subscribe method. I moved in and chained the promises and then passed the final value to your function parseFrontMatter
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With