Firebase firestore in the forum application #9: Implement Slug as URL params and Single app forum
Repository
What Will I Learn?
- Implement Slug as URL params
- Single app forum
Requirements
- Basic Javascript
- Install Firebase
Resources
- Firebase-https://firebase.google.com/
Difficulty
Basic
Tutorial Content
Hi everyone, we will continue the tutorial series on forum applications using firebase. if you have followed this tutorial before, of course, you know that we have made some features in this application, namely the auth system with social media, the firestore database structure, and the backend cloud function. well in this advanced tutorial we will still discuss the backend cloud function. We will focus on single forum data. for that, we just start this tutorial.
Single Forum
In the previous tutorial, when we saved data in firestore firebase we saved a data field called slug. well, here we will find out what is the use of slug.
- Slug as params
Slug is a concept that is often used in a single article instead of the id of the article. The slug will be generated uniquely to become a parameter in the URL showing the intended article. This method is mostly used in blog applications, social media, forums or news portals. like for example in steemit. let's see an example of using it in the picture below:
https://steemit.com/utopian-io/@duski.harahap/firebase-firestore-in-the-forum-application-6-forums-collection-and-add-data-in-collection-1559196649948
We can see in the picture above the slug shows an article page on steemit. Well, steemit generated the slug from the title of the article that was created and I think steemit added a timestamp (1559196649948)
to indicate when the article was created.
Well, the method that we have used by steemit on our application. we can see in the database that we use as shown below:
auth.js
var slug = title.toLowerCase().replace(/[^\w ]+/g, '').replace(/ +/g,'-');
db.collection('forums').add({
title : title,
slug : slug,
desc : desc.replace("<br />", "\n"),
created_at : new Date(),
updated_at : new Date(),
user : {
user_id : currentUser.uid,
username : currentUser.displayName
}
})
We can see in the code above we successfully generated slug in the following way title.toLowerCase().replace(/[^\w ]+/g, '').replace(/ +/g,'-');
.
Slug implementation on a single forum page
Now we will use the slug to display single forum pages because slug is something unique representing each forum created. We will use the slug as the parameter we passed in the forum URL.
- Pass parameter in URL
The thing to do is how we can pass the slug as a parameter to the URL used, here I will create a new URL and pass the slug, we can see below:
functions/index.js
app.get('/forum/:slug', function(req, res) {
// your code here
});
to pass parameters we can use :parameterName
. In this URL the name of the parameter to be used is :slug
and then, as usual, we get the request and the response to the function (req, res)
.
now how can we pass the value of the slug to the backend?, We can pass the slug through the frontend in the tag <a>
. The following is an example of the frontend that we made.
home.hbs
<h2>List of Forums</h2>
<ul>
{{#each dataForums}}
<li><a href="/forum/{{slug}}">{{title}}</a></li>
<span style="display:block;"><i><b>Desc :</b></i> {{desc}}</span>
{{/each}}
</ul>
We can pass these parameters to the tag <a>
as follows <a href="/forum/{{slug}}">{{title}}</a>
. We can get slug through the dataForums that we have rendered on the home.hbs page. {{slug}}
is a key that we store in the database generated from the title, the slug will be rendered as in the template shown below:
We can see above now that our URL has a slug, then we will use the slug to create a single page for each forum.
- Query for single page
We already have slug instead of the id, now we will use a slug in the parameter URL to* look up* the data in the database. Firebase Firestore has its own provisions for query. Here we will use the where ()
function. for more details, we can see in the example below:
functions/index.js
app.get('/forum/:slug', function(req, res) {
var forum = null;
db.collection('forums').where('slug', '==', req.params.slug).get()
.then(snapshot => {
snapshot.forEach(doc => {
forum = doc.data()
console.log(forum)
})
res.render('forum-detail', {forum:forum})
}).catch(err => {
console.log(err)
})
});
The query that we will do it in the URL forum/:slug
. to use the query where ()
function, we must have 3 parameters. The first parameter is the key or field 'slug'
. that we will look for in the database. The second parameter is the logical operator '=='
and the third is the data that will be searched in the database. The data we are looking for is Slug based on the parameters that are passed on the URL. We can access it like this req.params.slug
.
I will do a console log console.log(forum)
to see if the data we are looking for successfully appears, we can see in the picture below:
here I will create a variable var forum = null;
to store the contents of the document forum = doc.data()
. then we will send the variable to the frontend. such as the following res.render('forum-detail', {forum:forum})
. We can see here we will send the variable forum to the forum-detail
template. Now we will create the template first.
- Template forum-detail
In this section we will create a template from forum-detail.hbs, we take the template from the home.hbs template, the template is simple because we don't focus on the display we will only see the functionality of the functions we have created.
forum-detail.hbs
<!DOCTYPE html>
<html>
<head>
<title>{{forum.title}}</title>
</head>
<body>
<div class="jumbotron">
<h1 class="display-4">Hi, This the single forum. you can see any detail!</h1>
<hr class="my-4">
<p>It uses utility classes for typography and spacing to space content out within the larger container.</p>
<p class="lead">
<button class="btn btn-danger" type="button" name="button" onclick="login('gmail')">Login Gmail</button>
<button class="btn btn-primary" type="button" name="button" onclick="login('fb')">Login FB</button>
<button class="btn btn-info" type="button" name="button" onclick="login('twitter')">Login Twitter</button>
<button class="btn btn-success" type="button" name="button" onclick="logout()">Log out</button>
</p>
<hr>
<h2>Forum {{forum.title}}</h2>
<p>{{forum.desc}} <span><i>by: {{forum.user.username}}</i></span></p>
</div>
<script type="text/javascript" src="/assets/js/auth.js"></script>
</body>
</html>
As we have made above, we have passed the forum data to the forum variable, well because we have passed it we can render the contents of the forum variable on this template. Because the variable forum is in the form of an object we can render it like this {{forum.title}}
for title. forum.user.username for username because the username is on the object user.
If it's finished then we can see the results like the demonstration below:
We can see in the demonstration above we have successfully implemented slug as an id of a forum that is used to query the database so that we can get detailed data from the forum that we clicked on, until here is our tutorial this time. thank you, hopefully, it will be useful for you.
Curriculum
- Forum app
Firebase app#1, Firebase app#2, Firebase app#3, Firebase app#4, Firebase app#5
Thank you for your contribution @duski.harahap.
After reviewing your contribution, we suggest you following points:
Again: Nice work on the explanations of your code, although adding a bit more comments to the code can be helpful as well.
Be more careful with writing your tutorial!
Thanks for following some suggestions given in the previous tutorial.
Looking forward to your upcoming tutorials.
Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.
To view those questions and the relevant answers related to your post, click here.
Need help? Chat with us on Discord.
[utopian-moderator]
Thank you for your review, @portugalcoin! Keep up the good work!
Hi @duski.harahap!
Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server
Hey, @duski.harahap!
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!
Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).
Want to chat? Join us on Discord https://discord.gg/h52nFrV.
Vote for Utopian Witness!