How to configure Vue router to respond to query strings? - javascript

My router in configured as follows. It works and does what it's supposed to.
import Demo1 from "../vuex_modules/demo/demo1.vue"
import Demo2 from "../vuex_modules/demo/demo2.vue"
export const routes = [
{ path: "/demo/demo1", component: Demo1 },
{ path: "/demo/demo2", component: Demo2 }
];
Now, I need to match me some query strings. When I click in one of the views routed to above, I want the object pushed to the router to look like this.
export default {
methods: {
clicky: function(row) {
this.$router.push({ path: "", query: { id: row } });
}
}
}
I want the new URL, with ?id=123 added, to lead to another page (while demo2.vue is the table view, demo2_id.vue is supposed to be displayed upon a click and present details for the particular row being clicked.
According to Vue router docs, I'm suppose to add a colon when a part of URL is dynamic. I've tried different approaches, including the one below. I'm not routed to the page requested, though. Instead, I dwell still on the original page.
import Demo1 from "../vuex_modules/demo/demo1.vue"
import Demo2 from "../vuex_modules/demo/demo2.vue"
import Demo2_Id from "../vuex_modules/demo/demo2_id.vue"
export const routes = [
{ path: "/demo/demo1", component: Demo1 },
{ path: "/demo/demo2", component: Demo2 },
{ path: "/demo/demo2?:id", component: Demo2_Id }
];
Goolearching for vue router query strings leads to nothing that I can regard as useful (possibly due to ignorance)...

Case 1:
Following routes are two same route:
{ path: "/demo/demo2", component: Demo2 },
{ path: "/demo/demo2?:id", component: Demo2_Id }
Case 2:
While following are different:
{ path: "/demo/demo2", component: Demo2 },
{ path: "/demo/demo2/:id", component: Demo2_Id }
In first case: /demo/demo2?:id=213, you can get id as $route.query.id while in second case: /demo/demo2/:id, you will get id as $route.params.id.
Now if you want to have routes as in case 1: You will have single row in routes file and single route:
{ path: "/demo/demo2", component: Demo2 },
and you can write code to detect whether $route.query.id is present or not and load component accordingly with use of v-if
If you want to have routes as in case 2: you can add above two lines in routes file and treat them as two different routes.

Related

Vue Router not matching a url with multiple dynamic values

I am trying to add a nested url to my routes. So far, every route works fine except for the last one (see code below).
I also tried nesting the urls (using the children property), but was unsuccessful with that, and I don't think that's the approach I want to take here anyway, since I want to use an entirely separate component, and not nest the <router-view>s.
Any suggestions for what I should do? I'm not even sure how to debug. The Vue dev tools just show a <RouterView> component, with one prop: name: "default".
Here is my routes.js file:
import VueRouter from 'vue-router';
import Search from './views/Search';
import FoodItem from './views/FoodItem';
import NutrientCategory from './views/NutrientCategory';
import NutrientDetail from './views/NutrientDetail';
let routes = [
{
path: '/',
component: Search
},
{
path: '/:id',
component: FoodItem
},
{
path: '/nutrients/:slug',
component: NutrientCategory
},
{
path: '/nutrients/:slug/:nutrient-slug',
component: NutrientDetail
}
]
export default new VueRouter({
routes,
linkActiveClass: 'active',
scrollBehavior (to, from, savedPosition) {
return { x: 0, y: 0 }
}
});
The problem is that you try to use the minus sign as the parameter name:
/nutrients/:slug/:nutrient-slug
But the regular expression from the path-to-regexp package for parsing the path-pattern uses the \w character classe as the name-pattern:
\w+ matches any word character (equal to [a-zA-Z0-9_])
So use underscore instead of minus:
/nutrients/:slug/:nutrient_slug
[ https://jsfiddle.net/fhrekL25/ ]

modular routing in vuejs

I am building a simple website in which I have a route to category pages. I want to use a single dynamic route to move between pages.I am using vue-router for this project and the routes need to load different component
These are the desired routes for the website
example: '/shop/men' , '/shop/women','/shop/kids'
This my index.js file for router in which gender is appended in the last deciding which component to load the issue I am facing is how to handle this and load different component on depending on it
router-> index.js:
{
name: 'shop',
path: '/shop/:gender',
component: menCategoryViewsHandler('mencategory')
}
views -> viewHandler -> mencategory.js:
'use strict'
import Handle from '../mencategory.vue'
const camelize = str => str.charAt(0).toUpperCase() + str.slice(1)
// This is a factory function for dynamically creating root-level views,
// since they share most of the logic except for the type of items to display.
// They are essentially higher order components wrapping the respective vue file.
export default function ViewsHandler (type) {
console.log('1',type)
return {
name: `${type}-mencategory-view`,
asyncData ({store, route}) {
//#todo : add the ssr and routerbefore load change script here
return Promise.resolve({})
},
title: camelize(type),
render (h) {
return h(Handle,
{
props: {type},
},
)
},
}
}
You need to use dynamic route matching along with a wrapper component which renders the correct Category component. This would handled by passing props to components.
// CategoryResolver.vue
import menCategory from './mencategory'
import womenCategory from './womencategory'
import kidsCategory from './kidscategory'
const components = {
menCategory,
womenCategory,
kidsCategory
}
export default {
functional: true,
props: ['category'],
render(h, ctx) {
return h(`components[${category}Category`], ctx.data, ctx.children)
}
}
Then your router would be defined as such:
const router = new VueRouter({
routes: [
{ path: '/shop/:category', component: CategoryResolver, props: true }
]
})
Say menCategoryViewsHandler('mencategory') returns a component called MenCat. It must have a prop that matches the route above, in this example category. In MenCat you would define:
export default {
props: ['category'],
...
}
Vue router will pass the matching url prop into your component for you.

Angular: Child Route Matching

Suppose we have the following routes:
{
path: 'a',
component: AComponent,
children: [
{
path: '',
component: BComponent
},
{
path: '',
component: CComponent,
children: [
{ path: '', component: DComponent }
]
}
]
}
And the following URL is pasted into the browser's address bar:
http://localhost:4200/a
Questions
How does the Router know what component to display?
Would all the four components (A, B, C, D) be displayed?
Where would each component be displayed?
Does every parent component always have its own RouterOutlet, so each component along a route of parent/child/grand-child/etc. gets displayed inside its parent's respective RouterOutlet?
Usually, when displaying a route with child routes, each component is displayed inside its parent RouterOutlet. But, if only AComponent had a RouterOutlet, where would BComponent, CComponent and DComponent be displayed?
Given that you aren't getting any sort of error the router will give you the first matching route it found. In this case BComponent. Only one component can be shown in a router outlet (to do otherwise you need something like auxRoute).
If CComponent had a route like 'c' you could access it from the route http://localhost:4200/a/c then you would get CComponent with DComponent in CComponents router outlet.
Hope that helps.

Angular access methods of parent routes from child routes

So to explain clearly my problem, I have a component for each of my entities in my application like Author component and Book component. And for each of them I will have two child which is a list component and a form component.
So basically my route configuration look like this :
export const routing = RouterModule.forRoot([
{
path: 'author', component: AuthorComponent,
children: [
{ path: 'author-list', component: AuthorListComponent },
{ path: 'author-form', component: AuthorFormComponent }
]
},
{
path: 'book', component: BookComponent,
children: [
{ path: 'book-list', component: BookListComponent },
{ path: 'book-form', component: BookFormComponent }
]
}
]);
In my AuthorComponent for example I have a method to delete an author that call the service :
deleteBadge = (event): void => {
// Call delete service
this._badgeService.delete(event).subscribe(
result => {
// Good
},
error => {
// Error
}
My question is how can I call that method from my route child (author list or form component) knowing that I can't call it like a normal child component using event.
PS: I put method (and many other) in the parent because I need to access to it in both child components and so to avoid redundancy.
Standard practice is to use a shared service for Component Interaction. However, if you still want to avoid using a shared service, you can use the Injector API.
In your child component, AuthorListComponent for example, do the following:
import { Injector } from '#angular/core';
import {AuthorComponent} from "./author.component";
// ....
constructor(private injector:Injector){
let parentComponent = this.injector.get(AuthorComponent);
parentComponent.deleteBadge('String passed from AuthorListComponent');
}
Here is a link to working demo.
Use a communication Service which unites several communication observables.
An example can be found in the official Angular docs: https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service

Angular 2.4.0 Router: Named route. Error: Cannot match any routes

I am trying to understand how named routes work. I am trying to establish 2 router outlets. Here is the actual error that I am getting...
EXCEPTION: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'song/edit/58ab2f3907dc8edf2c4e6971'
Here are code snippets that show what I am trying to do...
app.routing.ts
const appRoutes: Routes = [
{ path: 'songs', component: SongsComponent},
{ path: 'song/edit/:id', component: SongsComponent, outlet: "details" }
];
app.component.ts
#Component({
template: `
<button (click)="showDetail($event,song)">Show Detail</button>
<router-outlet>Songs Here</router-outlet>
<router-outlet name="details">Song Detail Here</router-outlet>
`
export class AppComponent {
showDetail(event: any,song: Song) {
event.stopPropagation();
let link = ['/song/edit', song._id];
this.router.navigate(link);
}
}
});
As a side note, what I ultimately want to do is keep the SongsComponent in the DOM when I navigate to the SongComponent. With 2 router-outlets the SongsComponent will remain in the DOM where I can hide and show it without having to regenerate the DOM for the SongsComponent if it used the same router-outlet as the SongComponent.
Since you are trying to route to Named route, you need to mention same in the router command,
try below,
showDetail(event: any,song: Song) {
event.stopPropagation();
let link = [{
outlets: {
details: ['song','edit',song._id]
}
}];
this.router.navigate(link);
}
Here is the Plunker!!
Hope this helps!!

Categories

Resources