I have this url structure:
http://localhost:3000/apps/projects/update/5
How can I get the number 5 from the URL using Vue JS way?
I am trying with this code:
let urlParams = new URLSearchParams(window.location.search);
Thanks.
The best way to do that is to add vue-router to your project. Then you can define dynamic routes, like:
const routes = [
{ path: '/apps/project/:id', component: Project },
]
In this example, the :id defines a dynamic parameter. Than, in the Project component you can use the id variable:
const route = useRoute()
const urlParams = route.params.id;
Hope this helps.
Related
I'm implementing an paginated list. Therefore I'm using query parameters like ?size=10. This query paramter needs to be always inside my URL (like /home?size=2).
This apporach is not working:
const routes = [{ path: "/home", query: { size: "10" }, components: MyPage }];
const router = createRouter({
history: createWebHistory(),
routes,
});
I thought it is instantiating the route with some parameters. Looking into the Routing section of vue devtools shows me an empty query object:
$route:/home
fullPath:"/home"
path:"/home
query:Object (empty)
hash:""
name:undefined
params:Object (empty)
matched:Array[0]
meta:Object (empty)
redirectedFrom:undefined
href:"/home
How can I set a default query param to my route?
Here is a proposal using the beforeEach NavigationGuard:
const routes = [{ path: "/home", name: "Home", components: MyPage }];
const router = createRouter({
history: createWebHistory(),
routes,
});
router.beforeEach((to, from) => {
if(to.name === "Home" && !to.query.hasOwnProperty("size")){
to.query.size = "10"
}
})
The idea is to add to the route a default query parameter for size when it is not there.
The only way to achieve this properly without defining the default value in every router.push() is probably with Navigation Gurads. You can use them to get the query-parameters that are currently in the url, add the default query-params you need and then return the new route.
Though I would not do it, this is probably the easiest way to achieve this.
And if you want to make them customizable via pinia/vuex you would need to set up a store and make a user input to change the setting.
Note: Pinia is most likely the better option, because it is newer and will still be supported far in the future
I have a have a list of links inside a childcomponent which is integrated in different pages and if I click on a link, I need to get an id back, but I need to keep the current URL with the new id to call another method.
this.$router.push({path: '/page/', params: {id:id}})
this.$router.push({path: '/otherpage/', params: {id:id}})
I tried several things which are not working, like
this.$router.push({path: this.$router.currentRoute, params: {id:id}})
to get the following on different pages
http://domain/page/1
or
http://domain/otherpage/1
if I hardcode the path it works with:
this.$router.push(`/page/${id}`)
but I like to reuse the component on any page
thanks to Igor I ended up with the following:
const path = `/${this.path}/${node.id}`
if (this.$route.path !== path) this.$router.push(path)
thanks
From vue-router docs:
Note: params are ignored if a path is provided...
https://router.vuejs.org/guide/essentials/navigation.html
Instead of providing the path, you should call this.$router.push() with the route name, and the desired params.
For your example:
this.$router.push({name: this.$router.currentRoute.name, params: {id:id}})
This approach assumes that your routes are named, like this:
const routes = [
{
path: "/page/:id",
component: () => import('/path/to/component.vue'),
name: "nameOfTheRoute",
// other attributes
},
//...
]
I'm trying to use parameter only as a route as I need URL like localhost:8080/road. But, it's not working properly.
My code:
{
path: "/:id",
name: "id",
component: Blog
},
Whenever I enter a url like localhost:8080/dashboard or any other URL, it uses the Blog component. How can I solve it?
If your goal is to cut down on lines of code in your router definition, you could optimise this somewhat with an array of component names mapped to route definitions. For example
const components = ["Blog", "Road", "Dashboard"]
// creates kebab-cased slugs from Pascal cased component names
const toSlug = component =>
component.replace(/(?<=\w)[A-Z]/g, c => `-${c}`).toLowerCase()
const routes = components.map(name => ({
name,
path: toSlug(name),
component: () => import(`#/components/${name}.vue`)
})
Using static parts in the import path like #/components/ and .vue help Webpack optimise bundling.
I'm trying (unsuccessfully) to pre-render the HTML of multiple Vue apps within the same project scaffolded with Vue CLI. I do not want to use Vue Router or Nuxt etc for multiple reasons.
I've tried using prerender-spa-plugin, but since I don't use routes, it only pre-renders the index.
My vue.config.js looks like this:
const path = require('path');
const PrerenderSPAPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;
module.exports = {
pages: {
index: 'src/index.js',
about: 'src/about.js',
},
configureWebpack: {
plugins: [
new PrerenderSPAPlugin({
staticDir: path.join(__dirname, 'dist'),
routes: ['/'],
postProcess(route) {
route.html = route.html.replace('</script><div>', '</script><div id="app" data-server-rendered="true">');
return route;
},
renderer: new Renderer({
headless: true,
renderAfterDocumentEvent: 'render-event',
}),
}),
],
},
};
and my index.js and about.js essentially look like this:
import Vue from 'vue';
import App from './Index.vue';
new Vue({
render: h => h(App),
mounted() {
document.dispatchEvent(new Event('render-event'));
},
}).$mount('#app');
I also have unique public/ index.html and about.html pages.
The routes parameter of prerender-spa-plugin doesn't seem to recognise things like '/about.html'. Is there an easy way of achieving multiple pre-rendered pages?
Do I have to wrestle with the SSR module?
Thanks in advance.
The solution I've found is to call new PrerenderSPAPlugin multiple times, one for each route.
I'm also facing the same issue, i have static html uses vue component and i want to pre-render the vue component in output build directory. I'm using laravel-mix package for build process.
Could you post the full solution for this i.e calling new PrerenderSPAPlugin multiple times, one for each route.
If i can get the full webpack.config.js, it would easy for me to understand and implement the same using laravel-mix.
I have a use case for needing the id part of a vue route to contain unescaped forward slashes.
My current route looks like this:
{
path: '/browse/:path*',
component: browse,
name: 'browse',
displayName: 'Browse',
meta: { title: 'Browse' },
},
So when a user browses to the above url, the browse component is shown.
However, i want to use the id part of the path (:path*) to contain a nestable fielsystem like path to be consumed by my browse page.
For example the url /browse/project/project1 would take me two levels down in my tree to the project1 item.
Now, the problem i'm running into is that vue router is escaping my ids (path) when navigating programatically, and my url ends up like this: /browse/project%2Fproject1. This is non-ideal and does not look nice to the end user. Also, if the user does browse to /browse/project/project1 manually the app will work correctly and even keep the original encoding in the url bar.
So i could resolve this my making an arbitrary number of child paths and hope that the system never goes over these, but thats not a good way to solve my problem.
I should also clarify that the application will not know anything about the path after /browse as this is generated dynamically by the api that powers the app.
Is there a native way in vue-router to handale this? or should i change up how im doing things.
There is a more elegant solution without workarounds.
Vue router uses path-to-regexp module under the hood and constructions like
const regexp = pathToRegexp('/browse/:path*')
// keys = [{ name: 'browse', delimiter: '/', optional: true, repeat: true }]
https://github.com/pillarjs/path-to-regexp#zero-or-more
const regexp = pathToRegexp('/browse/:path+')
// keys = [{ name: 'browse', delimiter: '/', optional: false, repeat: true }]
https://github.com/pillarjs/path-to-regexp#one-or-more
set repeat flag to true. Any array parameter with repeat flag will be joined with the delimiter (default '/').
So you can pass a splitted array ['project','project1'] instead of 'project/project1' into router.push():
router.push( {name: 'browse', params: {path: ['project','project1']}} );
or
router.push( {name: 'browse', params: {path: 'project/project1'.split('/')}} );
So I managed to 'fix' this with a bit of a hack.
When creating my Vue router instance I am attaching a beforeEach function to replace any outgoing encodings of '/'. This will send the 'correct' URL I am looking for to the client.
const router = new Router({
mode: 'history',
routes,
});
router.beforeEach((to, from, next) => {
// hack to allow for forward slashes in path ids
if (to.fullPath.includes('%2F')) {
next(to.fullPath.replace('%2F', '/'));
}
next();
});
I just stumbled over your question while facing a similiar problem.
Think this is because an id shall identify one single resource and not a nested structure/path to a resource.
Though I haven't solve my problem yet, what you probably want to use is a customQueryString:
https://router.vuejs.org/api/#parsequery-stringifyquery
https://discourse.algolia.com/t/active-url-with-vue-router-for-facet-and-queries/3399
I fixed it by creating helpers for generating hrefs for :to attributes of vue router link.
First i made router accessible for my new helper service like here Access router instance from my service
Then i created router-helpers.js and here i made my helpers, here is an example
import Vue from 'vue'
import router from '../router.js'
// replace %2F in link by /
const hrefFixes = function(to) {
return to.replace(/%2F/g, '/')
}
// my link helper
Vue.prototype.$linkExample = attr => {
// create "to" object for router resolve
const to = { name: `route-name`, params: { param1: attr } }
// this will resolve "to" object, return href param as string
// and then i can replace %2F in that string
return hrefFixes(router.resolve(to).href)
}
Just include this service once in your Vue application an then just use this helper like this
<router-link :to="$linkExample(attr)">text</router-link>