Error when setting a route for page navigation - angularjs-routing

I am trying to set a route for page navigation in my app, but getting below error:
ERROR in C:/my-app/src/app/router.component.ts (9,2): Type '({ Path: string; redirectTo: string; PathMatch: string; } | { Path: string; component: typeof Abo...' is not assignable to type 'Route[]'. Type '{ Path: string; redirectTo: string; PathMatch: string; } | { Path: string; component: typeof Abou...' is not assignable to type 'Route'.
Code:
export const router: Routes=[
{Path:'', redirectTo:'about', PathMatch:'full'},
{Path:'about', component:AboutComponent},
{Path:'products', component:ProductsComponent},
];

Try without uppercase:
export const router: Routes=[
{path:'', redirectTo:'about', pathMatch:'full'},
{path:'about', component: AboutComponent},
{path:'products', component: ProductsComponent},
];

When you see these is not assignable to type 'X' exceptions, it is because the structure of the object literals don't match the Assignment structure (case-sensitive). This becomes clear when we check the Route interface:
export interface Route {
path?: string;
pathMatch?: string;
matcher?: UrlMatcher;
component?: Type<any>;
redirectTo?: string;
outlet?: string;
canActivate?: any[];
canActivateChild?: any[];
canDeactivate?: any[];
canLoad?: any[];
data?: Data;
resolve?: ResolveData;
children?: Routes;
loadChildren?: LoadChildren;
runGuardsAndResolvers?: RunGuardsAndResolvers;
}
As with most properties in javascript, path and pathMatch are defined in camel-case.
export const router: Routes = [
{path:'', redirectTo:'about', pathMatch:'full'},
{path:'about', component:AboutComponent},
{path:'products', component:ProductsComponent}
];

Related

Angular 14 migration: default routes and endless loops

I have the following configuration:
In the app.routes.ts
export const routes: Routes = [
{
path: '', pathMatch: 'full', redirectTo: environment?.firstTab ? environment.firstTab : 'releases',
data: {isInMenuBar: false}
},
{
path: 'login', component: LoginComponent,
data: {isInMenuBar: false, allowed: false}
},
....
}
and for the CanActivate:
#Injectable()
export class CanActivateMyApp implements CanActivate {
constructor(private router: Router) { }
canActivate(
route: ActivatedRouteSnapshot,
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if (this.userInfo) {
/*
* check further access
*/
}
return this.router.parseUrl('/');
}
Up till now (=Angular 13) this approached worked. If I don't have any kind of access ==> return to the top level path (=/) and continue the work. With Angular 14 this causes an endless loop.
Changing to return true or false works but I wonder if the approach is correct.
==> what is the correct way to handle the situation? Or did I miss something?

Nestjs Optional DTO during the Unit test

I have a simple controller:
#Patch('/:userId')
public async updateUser(
#Param('userId') userId: string,
#Body() userUpdate: UpdateUserDto): Promise<any> {
await this.usersService.update(userId, userUpdate);
}
The UpdateUserDto is:
import { IsEmail,IsString, IsOptional, MaxLength, IsNotEmpty} from "class-validator";
export class UpdateUserDto{
#IsEmail()
#IsOptional()
email:string;
#IsString()
#IsOptional()
password:string;
#IsString()
#MaxLength(30)
#IsNotEmpty()
#IsOptional()
name: string;
#IsString()
#MaxLength(40)
#IsNotEmpty()
#IsOptional()
username: string;
}
all fields are optional to create partial updates.
I don't have any error in my unit test if I use all fields
it('test', async () => {
const users = await controller.updateUser('10',{name: "testname",username:"fakeUser",email:"email",password:"S"});
});
but I get an error if I use part of it, like:
it('test', async () => {
const users = await controller.updateUser('10',{name: "testname",email:"email",password:"S"});
Argument of type '{ name: string; email: string; password: string; }'
is not assignable to parameter of type 'UpdateUserDto'.
Property 'username' is missing in type '{ name: string; email: string; password: string; }' but required in type 'UpdateUserDto'.
});
if password is optional (ie., can be undefined), then tell to TS it is: password?: string

Vue Router - catch all wildcard not working

I'm using Vue Router with Vue 3 and am trying to add a catch-all route to redirect the user if they try and access an invalid URL. When I try and use the wildcard (*), i get the following error logged to the console:
Uncaught Error: A non-empty path must start with "/"
at tokenizePath (vue-router.esm.js?8c4f:975)
at createRouteRecordMatcher (vue-router.esm.js?8c4f:1106)
at addRoute (vue-router.esm.js?8c4f:1190)
at eval (vue-router.esm.js?8c4f:1335)
at Array.forEach (<anonymous>)
at createRouterMatcher (vue-router.esm.js?8c4f:1335)
at createRouter (vue-router.esm.js?8c4f:2064)
at eval (index.js?a18c:26)
at Module../src/router/index.js (app.js:1402)
at __webpack_require__ (app.js:854)
I'm assuming this is because I don't prepend the path containing the asterisk with a '/', but if I do this then the catch all doesn't work. Here are my routes:
imports...
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/user',
name: 'User',
// route level code-splitting
// this generates a separate chunk (user.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "user" */ '../views/user/User.vue'),
children: [{path: '', component: UserStart}, {path: ':id', component: UserDetail}, {path: ':id/edit', component: UserEdit, name: 'userEdit'}]
},
{path: '/redirect-me', redirect: '/user'},
{path: '*', redirect: '/'}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
The wildcard route is the last object in the routes array. Does anyone know what I'm doing wrong?
Catch all routes (/*) must now be defined using a parameter with a custom regex: /:catchAll(.*)
For example:
{
// path: "*",
path: "/:catchAll(.*)",
name: "NotFound",
component: PageNotFound,
meta: {
requiresAuth: false
}
}
Personally, for Vue 2's * (star or catch all) routes in Vue 3 I use:
{
path: '/:pathMatch(.*)*', <== THIS
name: 'not-found',
component: NotFound
}
Catch all routes (*, /*) must now be defined using a parameter with a custom regex:
The parameter name can be whatever you want like catchAll, pathMatch, noPage etc
{
path: '/:pathMatch(.*)*', //will match everything and put it under `$route.params.pathMatch`
name: 'not-found',
component: NotFound
}
{
path: '/user-:afterUser(.*)',// will match anything starting with `/user-` and put it under `$route.params.afterUser`
component: UserGeneric
}
/:pathMatch(.*)*
The last * it is necessary if you plan on directly navigating to the not-found route using its name.
If you omit it the / character in params, it will be encoded when resolving or pushing.
For example if you use path: /:pathMatch(.*) (note: without the last asterisk) and you go to /user/not-found (a page that doesn't exists) the this.$route.params.pathMatch will be a string => 'user/not-found'
// bad example if using named routes:
router.resolve({
name: 'bad-not-found',
params: { pathMatch: 'not/found' },
}).href // '/not%2Ffound'
Instead, if you use path: /:pathMatch(.*)* (note: with asterisk) this.$route.params.pathMatch will be an array ['user', 'not-found']
// good example:
router.resolve({
name: 'not-found',
params: { pathMatch: ['not', 'found'] },
}).href // '/not/found'
Please read docs: From migration from vue 2 to vue 3 and Catch all / 404 Not found Route

TypeError: e is not a function

Good day.
When running my app i get the following error related to my vue-router:
TypeError: e is not a function
however i have nothing ... i simply named "e" in my code.
I have a few before each options but nothing too big besides a few cookies deletions.
I have a few imports of apps and i am trying to use them in my router and they all work. So does the cookies. I did the beforeEach() method a few times to see if the error was there but so far no luck.
i got no idea of what is going on.
EDIT: When trying to figure this i was comenting on my code to see if i could find the error and when i removed most of the beforeEach() section i left on the next() function and a new error showed sayin "t is not a function", so i guess for some reason java script is only recognizing the last letters of my funcions, like t in next() and e in some().
EDIT2: After removing unecessary code that i copied from another project apperently the error happens in my next() function.
here's my router code:
import Vue from "vue";
import Router from "vue-router";
import Dashboard from "#/views/Dashboard.vue";
import Opcoes from "#/views/settings.vue";
import LoginForm from "#/components/component/loginForm.vue";
import store from "./store.js";
import Cookies from "js-cookie";
Vue.use(Router);
let router = new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: "/",
name: "loginForm",
component: LoginForm,
meta: {
guest: true
}
},
{
path: "/dashboard",
name: "Dashboard",
component: Dashboard,
meta: {
requiresAuth: true
}
},
{
path: "/opcoes",
name: "Opcoes",
component: Opcoes,
meta: {
requiresAuth: true
}
},
{
path: "/sair",
name: "Sair",
component: LoginForm,
meta: {
requiresAuth: true
}
}
]
});
router.beforeEach((to, from, next) => {
const expirationDate = Cookies.get("expireIn");
const now = new Date().getTime();
if (now >= expirationDate) {
Cookies.remove("expirationDate");
Cookies.remove("token");
Cookies.remove("userId");
store.dispatch('LOGOUT');
} else {
next();
}
});
export default router;
Heres a print of my stack trace:
My Big Fat Guess
The error message points to line 2203 (line 1921 is part of a generic error handler). This line is in the Router push() method
onComplete && onComplete(route);
My guess is, somewhere in your code not shown in your question (perhaps in your LoginForm component), you are calling this.$router.push() with a second argument that is not a function, eg
this.$router.push({ name: 'Dashboard' }, somethingNotAFunction)
Other problems (from previous versions of the question)
Your / route (loginForm) has no params so this...
next({
path: "/",
params: { nextUrl: to.fullPath }
});
is invalid. Did you perhaps mean to send nextUrl as a query parameter. If so, use
next({ name: 'loginForm', query: { nextUrl: to.fullPath } })
You also have
next({ path: "login" });
and
next({ name: "login" });
neither of which exist in your routes. You should only forward the route request to existing routes.
Finally, if you're using Vuex, you should not be directly assigning state values. In strict-mode, this
store.state.isLoggedIn = false
will trigger an error. You should be committing state mutations instead.

Redirect Vue-Router on error in props function

I have this route definition:
{name: "article", path: "/article/:id", component: Article, props: true}
And this component (I use Typescript and vue-class-component):
#Component({
props: {
id: Number
}
})
class Article extends Vue {
id: Number;
}
Of course, this give me this warn
[Vue warn]: Invalid prop: type check failed for prop "id". Expected Number, got String.
So i update my route definition with a props function
name: "article",
path: "/article/:id",
component: Article,
props:(route:Route) => {
const id = parseInt(route.params.id);
if(isNaN(id))
throw new Error("id param should be a number")
return {id}
}
This works, but i don't find how to redirect user to a specific page if he gave me a "bad" value for id param ("/article/toto" for example)
router.onError seems don't works here
Navigation guards, where in can use next(error) can't modify params/props
Someone have any idea ?
All of the values in URL params are of type String.
In Your component, setup a watch for this specific property
props : ["id"],
watch : {
id(current,previous){
var reg = /^\d+$/;
if(reg.test(current)){
console.log("its a number");
}
else{
console.log("its not a number");
this.$router.push("/error"); //HomeComponent or ErrorComponent
}
}
}
Now as the watch is setup, you can check if your current value in prop is of type Number or String using Regex.
if currentValue is Number then
GoAhead
if currentValue is NAN then
Redirect to HomeComponent or ErrorComponent