VueJS View is not refreshing when I change the router paramId - vue.js

I have the following router that accepts a param ID
{
path: '/Filters/Edit/:id',
name: 'Manager.FilterEditor',
component: FilterEditor
},
When I try to navigate from one filter to another using router.push, the view remains the same.
router.push({ name: 'Manager.FilterEditor', params: { id: newfilter.id } });
The URL updates to the new ID, but the models remain the same.

You have to add a key attribute at the router-view in the master view.
<router-view :key="$route.path" />
The key will help VueJS to notice the change and trigger the model bounding and the view redraw.

Related

Route params value disappears after reload page in Nuxt JS

I use this.$router.push({name: 'nameComponent', params: {data:someObject}}) to switch pages. On the next page, params are detected when the page is first loaded. However, after reloading the page, params are no longer detected.
FYI, route configuration in Nuxt JS already uses history mode
You are using your router to share state between different components. On refreshing a route, the original data that was passed from page A to B is not retained - that behaviour is expected since you aren't accessing page A which is fetching the data.
If you want to be able to access data after a page refresh, you either need to fetch it again from the source in page B, cache it locally or change the way your components and routes work.
From Source
Fetching it from the source would mean you don't pass the actual data in the route, just the id and then fetch the data again in page B.
Downside
You might be fetching the same data twice
Local Storage
You can persist data you loaded in page A. You can either do this directly by
saving directly to local storage
using a library like localForage
using Vuex and the vuex-persist plugin
In page B you could access your local storage and retrieve the data from there.
Downside
This would still require the user to have visited page A at some stage and if that was a long time ago, data might be outdated if the user keeps visiting page B directly. It also means that you'd have to check if the data exists since the user might have cleared the cache.
Adjusting component and route architecture
Probably the way to go. You can create a parent component that fetches the data, and two child components that get the data passed as props, e.g.:
// Routes
cont routes = {
path: '',
name: 'parent',
compoent: Parent.vue,
children: [{
path: '/pageA'
name: 'pageA',
component: PageA
},
{
path: '/pageB'
name: 'pageB',
component: PageB
}
]
// Parent.vue
<template>
<router-view :user="user" />
</template>
<script>
export default {
data() {
return {
user: null
}
}
},
created() {
...fetch data
}
</script>
// PageA.vue & PageB.vue
<template>
...
</template>
<script>
export default {
props: {
user: {
type: Object,
require: true
}
}
}
</script>

Vue URL Updating but Component is not

Having an issue with my url updating but the page not.
From the home page, I display a list of projects. Clicking a project will take you to "website.com/project/project-1" and everything works as intended.
However, at the bottom of that page, I again show a list. This list is the same as homepage, with same functionality. But the problem is, is that it will update the url to "website.com/project/project-2" but the page will not re-render or change.
An example of my code
My current router-path of the component.
path: '/project/:project_slug',
name: 'ProjectPage',
component: ProjectPage
My Router Link from the project page to the new project page
<router-link :to="{ name: 'ProjectPage', params: {project_slug: projectHighlightSlug} }">
<h4 class="header-17 semibold">{{projectTitle}}</h4>
</router-link>
Update
This is my current method/watch section
methods: {
goToProject() {
this.$router.push({
name: 'ProjectPage',
params: {project_slug: this.projectHighlightSlug}
})
},
},
watch:{
// eslint-disable-next-line no-unused-vars
'$route'(to, from) {
this.goToProject();
}
}
However, the to,from is "defined but never used" and clicking my button to call goToProject() gives me the error;
"You may have an infinite update loop in watcher with expression "$route""
As explained in the Vue Router docs, when the url the user navigates to uses the same component, it uses the same instance of that component. The docs therefore recommend to listen to $route changes or to use the beforeRouteUpdate navigation guard.
You need to watch the routes to update your page. see code below
watch:{
'$route' (to, from) {
this.goToProject()
// call your method here that updates your page
}
},
source dynamic route matching

Where did I go wrong with vue-router configuration, or the problem is somewhere in my component?

I have list of users which I output in Home vue component. Every item in the list is coming from vuex and has it's own details. When I click any of this contacts list items vue-router takes me to route /contact/that-item-id for example contact/4536475. Now, when I am on that page for specific contact list item and refresh my browser vue app breaks, in other words I don't have access to that specific item object properties anymore.
Here is the code of my router
export default new Router({
routes: [
{
path: "/",
name: "Home",
component: Home
},
{
path: "/contact/:id",
name: "ContactDetails",
props: true,
component: ContactDetails
I am setting props property to true so I can pass it as params to contact item details component as so:
<router-link
class="view-more-btn"
:to="{ name: 'ContactDetails', params: { id: contact.id }}"
>VIEW DETAILS</router-link>
and at last I am passing that Id to my getters method in vuex to get details for clicked item as this:
export default {
props: ["id"],
computed: {
contact() {
return this.$store.getters.getContactDetails(this.id);
}
}
Where did I go wrong, why I can't refresh my contact item detail page and still preserve state I am using.
I am new to vue so please forgive me if I am not making sence. And ofcourse any help is welcomed, thanks in advance
The problem is probably, that you're referencing a named route and passing in the params by hand. This won't change the actual route displayed in your browsers address bar and only show the root path (/contact/ in your example I presume). Therefore when you refresh the passed in params/props simply don't exist anymore.
What you need to do instead is use a <router-link :to="'/contact/'+contact.id"> or <router-link :to="`/contact/${contact.id}`"">.
This should affect the URL in your browsers address bar to include the /contact/someID123 which will then also make the ID available on refresh.

Optional Parameter on Vue Router

So I have a project Page and when I click in one project I want to go to Project Detail page of that project. so I'm using dynamic routes. I pass as parameters a name(that will show on URL) and Id(that I use to go to my store and get the project, this Id is not showing on URL). Everything is ok, the problem is when I Load the browserinside the project Detail page, I only get name as a parameter and I cant get the Id so because of that I cant match the Id with my vuex because there is no Id.
this is my router-link on parent
<router-link class="project__icon" :project="project" :to="{ name: 'projectDetail', params: {name: project.name.replace(' ', ''), id: project.id} }">
and this is what I do on other page to get my project Id inside Vuex
const projectId = this.$route.params.id;
this.project = this.$store.getters.getProject(projectId);
This is what I get when I click on router
http://localhost:8080/project/myprojectName
On my router file I have this
{
path: '/project/:name',
name: 'projectDetail',
component: ProjectDetail,
},
I'm not sure why you are binding project to the router-link, shouldn't be necessary.
<router-link class="project__icon" :to="{ name: 'projectDetail', params: {name: project.name.replace(' ', ''), id: project.id} }">
You need to add :id as a parameter to your route. You can mark it optional with a ?.
{
path: '/project/:name/:id?',
name: 'projectDetail',
component: ProjectDetail,
}
Also, if you set props: true you can decouple your component from the router and instead of using this.$route.params.id, your detail component will receive the parameters as props.
{
path: '/project/:name/:id?',
name: 'projectDetail',
component: ProjectDetail,
props: true,
}
EDIT: You have to have the id in the url if you want to allow refreshing and still keep the id or you have to store it somewhere like localstorage or sessionstorage.

Declarative router link not clearing model in Vue component using VueRouter

Developing a task scheduler the path '/task?id=10' fills the component model with an async response with the task information, that works ok.
In the navigation bar I have the following router link:
<router-link to="/task">New Task</router-link>
So I am using the same path and component for creating a new task and editing existing ones all based in if "id" parameter is present or not.
The problem is that if I am in path '/task?id=10' and I fill some model fields, then I click the router-link pointing to '/task' (no params) it changes the browser URL but it does not clear the component model so the input data persists.
How can I restart/reload the component when landing it through a declarative router-link?
You can make parent-child component. Parent component is on /task route, child would be on '/task/10. More, Nested Routes. Also, you don't need to append '?id=', just /task/10.
const router = new VueRouter({
routes: [
{ path: '/task', component: Task,
children: [
{ path: ':id', component: TaskId }
]
}]
});
jsfiddle