This may have been asked but I have not be able to find a solution. I have a index page that loads a left nav vue. On that view is a typeahead input with names. When a name is selected a function is called and and a unique value is passed as the pmid_list
this.$router.push({ name: 'About', params: { pmid_list: item.PMID_Include } }
This works fine the first time because the About vue is loaded and the function is called with the pmid_list value. Every name works fine if I refresh the page between calls. If I don't refresh the correct pmid_list (parameter) is sent to the router but the router decides to send the old one if the vue component has not changed.
From what I have read it is a router issue but I can't figure out how to force it to refresh.
export default new Router({
mode: 'history',
routes: [
{
path: '/about/:pmid_list',
name: 'About',
component: About,
props: {default: true}
}
The About component is being cached.
One thing to note when using routes with params is that when the user navigates from /user/foo to /user/bar, the same component instance will be reused. Since both routes render the same component, this is more efficient than destroying the old instance and then creating a new one. However, this also means that the lifecycle hooks of the component will not be called.
Dynamic Route Matching
As shown in the documentation, you should use a watcher to react to parameter changes:
watch: {
'$route' (to, from) {
// react to route changes...
}
}
You can try to watch your route changes.
watch:{
'$route.params.pmid_list': function (pmid_list) {
//your logic here
}
},
Related
Say I have 2 routes '/users' and /users/:id. First one renders UserListComponent and second UserViewComponent.
I want to re-render component when navigating from /users/1 to /users/2. And of course if I navigate from /users to /users/1 and vice versa.
But I DON'T want to re-render component if I navigate from /users/1?tab=contacts to /users/1?tab=accounts.
Is there a way to configure router like this for entire application?
--
Update:
I'm importing RouterModule in AppRoutingModule like this:
RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })
I'm using Angular 12
The default behavior of the Angular router is to preserve the current component when the URL matches the current route.
This behavior can be changed by using the onSameUrlNavigation option:
Define what the router should do if it receives a navigation request
to the current URL. Default is ignore, which causes the router ignores
the navigation. This can disable features such as a "refresh" button.
Use this option to configure the behavior when navigating to the
current URL. Default is 'ignore'.
Unfortunately, this option is not fine-grained enough to allow reload for path params and ignore for query params.
So you have to subscribe both to the query params and the path params changes with something like this:
constructor(route: ActivatedRoute) { }
ngOnInit() {
this.renderLogic();
this.route.params.subscribe(() => this.renderLogic());
this.route.queryParams.subscribe(() => this.renderLogic());
}
renderLogic() {
// ...
}
As far as I know, #Guerric P is correct, you can't completely re-render the component selectively like this, at least not without some trickery like subscribing to each event and then possibly blocking it for one scenario and not the other. Feel free to try something like that, but below is an alternative if you make use of resolvers to fetch your data.
What you can do is use runGuardsAndResolvers in your route configuration like so:
const routes = [{
path: 'team/:id',
component: Team,
children: [{
path: 'user/:name',
component: User
}],
runGuardsAndResolvers: 'pathParamsChange',
resolvers: {...},
canActivate: [...]
}]
This will, as the name suggests, run your guard resolver logic again. If you fetch data using resolvers and pass it into your components, you can update what your component displays only when the path or params change.
I am new at Vue.js. I am working on demo project. In my project, I have three different navbar. First one for HomePage, second one for Login/Register page and third one is for Dashboard. In frameworks like React and Vue we set one global navbar for all pages. How can I render this three navbar components conditionally ? What is the best practice for that ? I want to set vuex for solve that, is that a right approach ?
You can do it using named routes. In your component you set multiple named router views:
<router-view name="navbar"></router-view>
<router-view ></router-view>
And in routes you set which component to render and where:
const router = new VueRouter({
routes: [
{
path: '/',
components: {
default: HomeContent,
navbar: HomeNavbar,
}
},
{
path: '/dashboard',
components: {
default: DashboardContent,
navbar: DashboardNavbar,
}
}
]
})
Otherwise you can set a conditional in the component and render navbar based on route:
if ($route.path === home) {
<NavbarHome />
}
If navbars have much in common you can just use a conditional for elements that are in one but not in another.
Actually what you can do is make a navbar component and use v-if to check on which route you are currently on. You can use the $route object to verify the current URL and use computed to check if the route name or params/queries are the same as you want.
computed: {
dashboard() {
return this.$route.name === 'Dashboard'
}
}
And then in your navbar component use v-if="dashboard" to check your conditions
The Angular Routing docs mention component instance creation, component instance activation, and route activation.
The docs do not explain the differences of these concepts, and when each creation/activation occurs.
Questions
What is the difference between instance creation and instance activation?
What is the difference between instance activation and route activation?
Does instance activation always occur at the same time as instance creation?
In summary: It is not clear what is really meant by component instance activation and route activation, and how that relates to component instance creation (particularly timing wise).
Known Information
Instance Creation
Component instances are created by Angular when navigating between components of different types
When navigating between instances of the same component, the instances are re-used by default
Instance Activation
When browser's location URL changes to match a path segment (e.g /crisis-center), Router activates an instance of corresponding component (e.g CrisisListComponent) and displays its view
When app requests navigation to a path (e.g /crisis-center), Router activates instance of corresponding component (e.g CrisisListComponent), displays its view, and updates browser's address location and history with URL for that path
Route Activation
Mentioned a few places throughout the docs. See below
Angular Doc References
Here are some mentions of the above three concepts, in the Angular docs:
Instance Creation
By default, the router re-uses a component instance when it
re-navigates to the same component type without visiting a different
component first.
...
This application won't re-use the HeroDetailComponent. The user always
returns to the hero list to select another hero to view. There's no
way to navigate from one hero detail to another hero detail without
visiting the list component in between. Therefore, the router creates
a new HeroDetailComponent instance every time.
Link
Instance Activation
When the browser's location URL changes to match the path segment
/crisis-center, then the router activates an instance of the
CrisisListComponent and displays its view.
Link
When the application requests navigation to the path /crisis-center,
the router activates an instance of CrisisListComponent, displays its
view, and updates the browser's address location and history with the
URL for that path.
Link
Route Activation
The data property in the third route is a place to store arbitrary
data associated with this specific route. The data property is
accessible within each activated route.
Link
You can also protect child routes with the CanActivateChild guard. The
CanActivateChild guard is similar to the CanActivate guard. The key
difference is that it runs before any child route is activated.
Link
In the Hero Detail and Crisis Detail, the app waited until the route
was activated to fetch the respective hero or crisis.
Link
The ActivatedRouteSnapshot contains the future route that will be
activated and the RouterStateSnapshot contains the future RouterState
of the application, should you pass through the guard check.
Link
What is the difference between instance creation and instance
activation?
Instantiating means creating an instance of a route (ActivateRoute) or component. Activating of a route means attaching it to the router-outlet directive. Activating of a component means attaching it to the DOM. Routes and components are activated using activateWith function of a router-outlet directive.
Let's see some examples. Suppose you have the following routes:
{
path: 'a',
component: AComponent,
children: [
{ path: 'b', component: BComponent },
{ path: ':name', component: DComponent }
]
}
Now you navigate to a/b.
The router will:
instantiate { path: 'a', component: AComponent, children: [] } route
instantiate { path: 'b', component: BComponent } route
activate these routes by attaching them to the respective router-outlet locations
instantiate AComponent and BComponent using this approach
activate AComponent and BComponent by adding them to DOM
Now you navigate to a/n1.
The router will:
reuse route for a - { path: 'a', component: AComponent, children: [] } route (no instantiation or activation)
instantiate { path: ':name', component: DComponent } route
activate { path: ':name', component: DComponent } route
reuse AComponent instance (no instantiation or activation)
instantiate DComponent instance
activate DComponent by attaching it to the router-outlet in AComponent view
Now you navigate to a/n2.
The router will:
reuse route for a - { path: 'a', component: AComponent, children: [] } route (no instantiation or activation)
reuse route for n2 - { path: ':name', component: DComponent } route (no instantiation or activation)
update params for the n2 activated route
reuse DComponent instance (no instantiation or activation)
I'm using vue.js and I have one component, where the user selects what they want and then they hit "order". At this moment I use <router-link to="/order"> to show new page. But I don't know how to access the array from the previous component there. I tried something like this :selected-chairs="selectedChairs" and in the other component this props: ['selectedChairs'], but it doesn't work.
My routes file (index.js):
export default new Router({
routes: [
{
path: '/',
name: 'Select',
component: Select,
props: true
},
{
path: '/order',
name: 'Order',
component: Order,
props: true
}
]
})
It's possible to do what you want to do but I don't think it's a good idea. First, in line with your original question, this is what you could do:
Set up your order route:
export default new Router({
routes: [{
path: '/order/:selected-chairs',
name: 'Order',
component: Order,
props: true
}]
}
You could then have a link like so:
<router-link :to="'/order/' + JSON.stringify(mySelectedChairs) + '">Link Text</router-link>
or you could do
<router-link :to="{path: 'order', query: { selected-chairs: mySelectedChairs }}">Link Text</router-link>
This would allow you to access that data on your component using:
this.$route.params.selected-chairs
or
this.selectedChairs // because props: true binds to the props
This page has more information on passing params using router-link: https://router.vuejs.org/en/api/router-link.html
As I said, I don't think this is a good idea. Even if you're not using Vuex, you're much better off doing this using some sort of stateful component. You could then set the selected-chairs in your state and the order component would just know about them being selected. This allows you to do things like having a mini basket that reacts to users entering stuff into their baskets etc.
Setting up a simple Vuex system isn't complicated and there are various articles on the web to help that would be my recommended approach.
The above answer is correct but will show a blank page on page load.
To solve that, DO:
export default new Router({
routes: [{
path: '/order/:selected-chairs?',
name: 'Order',
component: Order,
props: true
}]
}
As you can see, I added a question mark (?) to the front of the path parameter
I have an Angular 2 test app running the latest alpha (37). There are just three routes, that look like this:
#RouteConfig([
{ path: '/', component: Home, as: 'home' },
{ path: '/errors', component: Errors, as: 'errors' },
{ path: '/about', component: About, as: 'about' }
])
I can access the routes, and when I place query string params in the URL I can read them just fine. However, a few instants after I read the parameters, I noticed that the route loads fine and the URL refreshes, removing the query string parameters.
In other words, accessing this route:
http://localhost:5555/errors?test=abc
Loads the /errors route, but right after the application loads the URL turns into:
http://localhost:5555/errors
That would be confusing to a user. I would like to keep the query string parameters in the URL.
I know, it's in alpha, but is this a bug or I forgot to set something up on the router? How can I keep whatever query string parameters in the URL?
Thanks!
This is fixed in Alpha 41. The query string is now persisted.
Updating for Angular 2:
To preserve query parameters present in the current url, add
// import NavigationExtras
import { NavigationExtras } from '#angular/router';
// Set our navigation extras object
// that contains our global query params
let navigationExtras: NavigationExtras = {
preserveQueryParams: true
};
// Navigate to the login page with extras
this.router.navigate(['/someLink'], navigationExtras);
For more info, check here:
Try this
this.router.navigate(['target'], {preserveQueryParams: true});