Adding URL friendly slugs - meteor

Currently what i have is
http://www.example.com/_id
instead of displaying the generated id in the url i want to show the title of my post in the url. Such as
http://www.example.com/this_is_a_new_post
do i have to add the slug field in the collection for this? isn't there any any solution using which i can make a friendly url and i don't have to make another redundant field like slug?
P.S. I don't want to use packages. i guess it can be done without packages easily.

The simplest thing you can do is just to use /:title. Iron will automatically decode the title. Firefox handles such URLs pretty nicely. It just converts them, so the user sees the actual title including all special-chars. Also, all the iron helpers are encode the URL string correctly.
To create a slug you can use something like this function:
createURLSlug = function (url) {
var slugRegex = /[^\w\-\.\~]/g
while(slugRegex.test(url)) {
url = url.replace(slugRegex, '-')
}
return url
}
I used the wiki page on of allowed URL characters as a reference for this regex.
If you are using SimpleSchema you can also use an autoValue:
...
slug: {
type: String,
autoValue: function () {
return createURLSlug(this.field('title').value)
}
}
...

Related

how to add dash(-) between name of dynamic route Nextjs in url

I create a dynamic route pages/post/[postname].tsx . and when I send name to the dynamic route the url shows name with url-encode (%20,%E2,...)
I want to show name of the url with dash between words. like below url
https://stackoverflow.com/questions/68041539/using-dash-in-the-dynamic-route-name-in-nuxt-js
how can I do this?
I've used the getStaticPaths method and pass it an object of slugs before. This has worked for me when dealing with a headless CMS'.
export async function getStaticPaths() {
// Hit API to get posts as JSON
const posts = await getPosts()
// Map a new object with just the slugs
const paths = posts.map((post) => {
return { params: { slug: post.slug } }
})
// Return paths
return {
paths: paths,
fallback: true
}
}
I think I understand the problem, you're trying to use a set of strings with spaces e.g "the fundamentals of starting web development" as path param to achieve something like this https://www.geniushawlah.xyz/the-fundamentals-of-starting-web-development. That will most likely convert your spaces to %20 which is normal. I would have advised you to first use replace() method to change all spaces to hyphen before passing it as param but the replace() method only changes the first space and leave the rest. There are other ways to get rid of the spaces programmatically but may be stressful and not worth it, so I'll advise you use an hyphenated set of strings by default.
If not, try to use a for-loop with the replace() method to change all spaces to hyphens, then pass it as param.

How to extract params from received link in react native firebase dynamiclink?

I tried to migrate from react navigation deeplinks to firebase dynamic linking using this library (react-native-firebase).
I have set up everthing and links are being generated and received on the app. However, is there any way to extract the params sent in the link properly using this library?. Currenty this is my code for handling received link:
handleDynamicLink = () => {
firebase
.links()
.getInitialLink()
.then((url) => {
console.tron.log('link is ', url);
})
.catch((error) => {
console.tron.log(error);
});
};
The url received is
https://links.dev.customdomain.in/?link=products%2F1122
I want to extract the product id 1122 from the url. The only way for me right now is to parse the string and manually extract the relevant params. Unlike in react navigation deeplinks where I used to specify the path, like
Product: {
screen: Product,
path: 'customdomain/products/:slug',
},
Where the slug or id data used to pass as navigation param in the respective screen. Am I missing something? How can I pass mutliple params this way?
Point 2 in this link here says:
The response contains the URL string only.
This means that the firebase.links().getInitialLink() method does not return query parameters, at least as at the time of writing this (v5.5.5). To add your paramaters, you should use a URL with your query param as part of the URL. What I mean is this
Use https://links.dev.customdomain.in/link/products/1122
and use Regex to extract the product id which is of interest to you. This is what works for me and I hope it helps.

Understanding how Router.go() works in Meteor

I'm just learning Meteor now from the great Discover Meteor book and I'm struggling to understand something about how Router.go() functions which I thought might be something that other beginners could use an answer to.
Context: The code below does what it's supposed to - it picks up the url and title values from the postSubmit form (code not included for the form) and uses that to create a new post. Then it uses Router.go() to take the user to the postPage template at a posts/:_id url, displaying the information for the newly created post. This code all works.
My question is: I would expect that when you call Router.go(), as well as passing in the 'postPage' template, what you would need to pass in as the second parameter is the post id element in the form {_id: post._id} (which also works, I've tried it) as that is what the route requires. So why am I passing in the post var (which includes the url and title) rather than the ID?
Here's my code:
//post_submit.js
Template.postSubmit.events({ 'submit form': function(e) {
e.preventDefault();
var post = {
url: $(e.target).find('[name=url]').val(),
title: $(e.target).find('[name=title]').val()
};
post._id = Posts.insert(post);
//THE 'post' PARAMETER HERE INSTEAD OF '{_id: post._id}' IS WHAT I'M QUESTIONING
Router.go('postPage', post);
}
});
And the code for the router:
//Route for the postPage template
Router.route('/posts/:_id',
{name: 'postPage',
data: function(){ return Posts.findOne(this.params._id); }
});
Good question - I also found this confusing when I first saw it. Here's a sketch of what's going on:
The router parses /posts/:_id and figures out that it should be passed a context object which contains an _id field.
You call Router.go with a context object that contains an _id field.
The router takes your context object and copies the value of _id into this.params.
Because the router understands which fields are required (and ignores the rest), it doesn't actually matter if you pass in {_id: 'abc123'} or {_id: 'abc123', title: 'hello', author: 'bob'}. The fact that the latter works is simply a convenience so you don't have to extract the _id into a separate object.

How to use URL parameters using Meteorjs

How can I use URL parameters with meteor.
The URL could look like this: http://my-meteor.example.com:3000?task_name=abcd1234
I want to use the 'task_name' (abcd1234) in the mongodb query in the meteor app.
eg.
Template.task_app.tasks = function () {
return Tasks.find({task_name: task_name});
};
Thanks.
You are probably going to want to use a router to take care of paths and rendering certain templates for different paths. The iron-router package is the best one available for that. If you aren't using it already I would highly recommend it.
Once you are using iron-router, getting the query strings and url parameters is made very simple. You can see the section of the documentation here: https://github.com/iron-meteor/iron-router/blob/devel/Guide.md#route-parameters
For the example you gave the route would look something like this:
Router.map(function () {
this.route('home', {
path: '/',
template: 'task_app'
data: function () {
// the data function is an example where this.params is available
// we can access params using this.params
// see the below paths that would match this route
var params = this.params;
// we can access query string params using this.params.query
var queryStringParams = this.params.query;
// query params are added to the 'query' object on this.params.
// given a browser path of: '/?task_name=abcd1234
// this.params.query.task_name => 'abcd1234'
return Tasks.findOne({task_name: this.params.query.task_name});
}
});
});
This would create a route which would render the 'task_app' template with a data context of the first task which matches the task name.
You can also access the url parameters and other route information from template helpers or other functions using Router.current() to get the current route. So for example in a helper you might use Router.current().params.query.task_name to get the current task name. Router.current() is a reactive elements so if it is used within the reactive computation the computation will re-run when any changes are made to the route.

iron-router: replace special characters

To get understandable links to share, I don't want to put only the ._id in the url but the .name as well.
Router.map(function () {
this.route('here', {
path: 'here/:_id/:name/',
template: 'here'
})
})
The Problem is that the .name entry can have special characters like /.
www.example.com/here/1234/name_with special-characters like / (<-this slash) /
Is there a way to replace the slash (and other special characters) in iron-router?
(if there is a good way to handle this, maybe in some cases I don't even need the id anymore.)
If I want to use <a href="{{pathFor 'showCourse'}}">
I can not use a wildecardpath: 'here/:_id/*
Thanks
It's not specific to Iron Router, but JavaScript's native global functions encodeURIComponent and decodeURIComponent exist for just this purpose:
encodeURIComponent("foo/bar"); // returns "foo%2Fbar"
decodeURIComponent("foo%2Fbar"); // returns "foo/bar"
What I do in my projects is add a field called slug and write a function that generates an URL-friendly slug from the document's title and checks the collection to make sure the slug is unique (otherwise it appends "-2" or "-3" etc. as appropriate). With a slug or similar field that is unique per document, you can use it as the only query parameter and forgo the _id.
Expanding on Geoffrey Booth's answer, you can do this with a template helper.
Define a template helper to encode your name value (I made it global so it can be reused by all templates):
Template.registerHelper('encodeName', function() {
this.name = encodeURIComponent(this.name);
return this;
});
Then, in your templates, you can pass this function to iron-router's pathFor helper:
<a href="{{pathFor 'showCourse' encodeName}}">
This works for me on Meteor 1.1.0.2.

Resources