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.
Related
I would like to target only the page which does not have specific query param. Value does not matter, what matter is that the params is not in the url, and only then run the experiment.
I tried to use matches regex but does not work:
Regex I use: ^[a-zA-Z]+
It can be done using custom JS func variable like this
function () {
return window.location.search.includes('nameOfYourParam')
}
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.
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)
}
}
...
I have an app where you can choose (or add if they don't exist!) a superhero/villain character from a certain universe on the first page; then outfit him with weapons, clothes, and gadgets on the second page (build).
I have this route defined:
Router.route('/build/:character', {
name: 'build'
waitOn: Meteor.subscribe('characters', {name: this.params.character})
//and a few other subscriptions and sessions as well for the items
//and stuff, but those don't matter here.
}
The link from the specific character, though, passes along a query as well:
<a href="{{pathFor 'build' query=this.universe}}">
So the final link could look something like this:
/build/Aquaman?DCComics
Now the page you are on will display a list of weapons and gadgets where you could also add other stuff if you so wish. Then you are supposed to drag the items you want to include onto your version of this hero.
Problem is, at this point the app doesn't know you even want to create your own hero. Maybe the user is just looking through them for fun. There's a button that the user has to click first to initialize the creating process, and that's when the actual _id is created, something like this:
Meteor.methods({
buildHero: function(heroCharacterName, heroUniverse) {
var heroToAdd = {}
heroToAdd['characterName'] = heroCharacterName
heroToAdd['universe'] = heroUniverse
heroToAdd['_createdAt'] = new Date()
CreatedHeroes.insert(heroToAdd, function() {
if (! error)
//Update the subscription somehow...
})
}
})
So, the _id that is created here in the new Collection must be passed along to a subscription somehow, because I don't want the user to see other personal heroes that have been created, only his own newly created one.
The solution I have in mind is adding the _id onto the URL in form of a hastag, and use this.params.hash in the subscription like so:
Router.route('/build/:character', {
name: 'build'
waitOn: [Meteor.subscribe('characters', {name: this.params.character}),
Meteor.subscribe('createdheroes', this.params.hash)]
}
First of all, is this a valid approach? If so, how do I accomplish it; how do I actually update the URL to include this hash?
If not, what would be a better approach?
I think you have to handle this logic in the data context or in a template helper and not in the way of subscribing/publishing.
If I was you I would besure that the newly created item is being published and subscribed by the client and modify your search query just that it only adds the newly created item.
I am not sure if I understand your question well but what I got, you will know the last _id which was used on your insert.
Instead of letting done this automatically by meteor, just use the meteor method to create / get that _id value >> see Meteor Documentation
var new_id = new Mongo.ObjectID()
col1.insert({ _id: new_id, ... });
col2.insert({ ..., ref_col1_id: new_id, ... });
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.