Routing with if condition in vue.js - javascript

This is my code within in router.js file
{
name: "Admin",
path: "/admin/",
component: () => import("#/views/admin/Index"),
children: [
// Dashboard
{
name: "Dashboard",
path: "dash",
component: () => import("#/views/admin/Dash"),
},
{
name: "Campaign Management",
path: "campaign",
component: () =>
import("#/views/CampaignManagementNew/CampaignManagment"),
},
]
}
I set a variable 'status' in the localStorage.
I want to route only, if 'status' is true (localStorage item).
Otherwise, I not need to routing to child components.
How I use if conditions to routing?

You want to implement a pretty common pattern for 'protecting' routes behind a flag. In order to accomplish this, you should add a meta property to the routes you want to 'protect' behind a secondary check (the localStore value). Then you will need to create a router guard that checks the meta flag and routes the user based on those conditions.
You can see an example of it here: https://router.vuejs.org/guide/advanced/meta.html#route-meta-fields
In your case you would want to replace the auth.loggedIn() with your function that can check the localStorage value. So something like this:
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresLocalStorageValue)) {
if (!checkLocalStorageValue()) {
next({ path: '/not-authorized-page-missing-local-store'})
} else {
next()
}
} else {
next() // make sure to always call next()!
}
})

Related

Redirect to 404 page without modifying the URL in Vue.js

In my Vue.js project, I want to display my 404 page, if a route parameter is invalid. For now, I'm using the following code for that:
this.$router.replace({ path: '/404' });
Is there a way to do that without modifying the URL? I want the user to still be able to copy the browser's original URL line. Is there some kind of a silent: true parameter?
With vue-router, the URL is the source of truth. If the URL changes, so does the rendering. You can't "pause" the router. (This is a flaw in vue-router that has been bugging me for ages, but I digress.)
You just have to display the 404 page without modifying the route. Have some display404 data property in your root component that you can set to display the 404 page manually in the template instead of the <router-view>, e.g:
<div>
<my-404-page v-if="display404"/>
<router-view v-else/>
</div>
To display the 404 page from any component:
this.$root.display404 = true
Of course this is just a basic example to demonstrate what I mean, you might want to use Vuex to share the state, or use an event bus, or you can display the 404 page in some other way that works for you, etc.
This was fixed in Vue Router 4 which you can see on the second example in the docs.
Build your NotFound route like this:
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: NotFound
},
Then you can use a beforeEnter navigation guard on your dynamic Vue like so:
// In your router/index.js file...
{
path: 'users/:id',
name: 'User Detail',
component: UserDetail,
beforeEnter(to, from) {
// See if that query exists in your data...
const exists = data.users.find(
user => user.id === parseInt(to.params.id)
)
if (!exists) {
// THE IMPORTANT PART
// Return your not found view...
return {
name: 'NotFound',
// Match the path of your current page and keep the same url...
params: { pathMatch: to.path.split('/').slice(1) },
// ...and the same query and hash.
query: to.query,
hash: to.hash,
}
}
}
}
Haven't tested this in a Component yet, but I'd assume it'd be the same logic in the beforeRouteEnter navigation guard.
Not 100% sure what you are asking, but is either of these any help?
A catch all route:
From Vue.js docs "Catch all route"
Or if you are managing a response form a call (method/fetch/ etc): Use a combination of try/catch and a "loading" data value to change the display or what component is loaded.
Based on Decade Moon's solution, I did the following:
main.js
import Error404 from './views/error/404.vue'
Vue.component('error-404', Error404)
404.vue
<template>
<div>
<h1>Page not found</h1>
<p>Whatever...</p>
</div>
</template>
<script>
export default {
name: 'Page not found'
}
</script>
router --> index.js
const PageNotFound = () => import('#/views/error/404')
function configRoutes() {
return [
{
path: '/',
name: 'Home',
component: TheContainer,
children: [
// ...
{
path: '404',
name: 'Page not found',
component: PageNotFound,
alias: '*'
}
]
}
]
}
My Page which should display the 404 error
<template>
<div class="animated fadeIn" v-if="clientSettings">
...
</div>
<error-404 v-else></error-404>
</template>
<script>
export default {
name: 'Test',
data() {
return {
clientSettings: null
};
},
async created() {
this.setClientConfig();
},
watch: {
'$route.params.id': function (id) { this.setClientConfig(id);}
},
methods: {
setClientConfig(id) {
if (!id) {
id = this.$route.params.id;
// Redirect to the first valid list, if no parameter is proviced
if (!id) {
this.$router.push({ name: 'Test', params: { id: this.$root.clientConfiguration[0].name } });
return;
}
}
// Set client settings
this.clientSettings = this.$root.clientConfiguration.find(cc => cc.name === id);
// This will return null, if no entry was found, therefore the template will jump into the v-else
}
}
}
</script>

How to create a middleware for check role in Nuxtjs

I'm trying to create a middleware for check role of my users.
// middleware/is-admin.js
export default function (context) {
let user = context.store.getters['auth/user']
if ( user.role !== 'admin' ) {
return context.redirect('/errors/403')
}
}
In my .vue file, I'm putting this on:
middleware: [ 'is-admin' ]
It works.
Now, I'd like to check if the user also has another role. So, I create a new middleware:
// middleware/is-consultant.js
export default function (context) {
let user = context.store.getters['auth/user']
if ( user.role !== 'consultant' ) {
return context.redirect('/errors/403')
}
}
And in my .vue file:
middleware: [ 'is-admin', 'is-consultant' ]
Unfortunately, when I do that, if I visit the route with an administrator role, it does not work anymore.
Can you tell me how I can create a middleware that checks multiple roles with Nuxt.js?
Thank you!
The idea is that every page has its authority level. Then in middleware you can compare your current user authority level with the current page authority level, and if it's lower redirect the user. It's very elegant solution that was proposed by Nuxt.js creator. GitHub issue.
<template>
<h1>Only an admin can see this page</h1>
</template>
<script>
export default {
middleware: 'auth',
meta: {
auth: { authority: 2 }
}
}
</script>
Then in your middleware/auth.js:
export default ({ store, route, redirect }) => {
// Check if user is connected first
if (!store.getters['user/user'].isAuthenticated) return redirect('/login')
// Get authorizations for matched routes (with children routes too)
const authorizationLevels = route.meta.map((meta) => {
if (meta.auth && typeof meta.auth.authority !== 'undefined')
return meta.auth.authority
return 0
})
// Get highest authorization level
const highestAuthority = Math.max.apply(null, authorizationLevels)
if (store.getters['user/user'].details.general.authority < highestAuthority) {
return error({
statusCode: 401,
message: 'Du måste vara admin för att besöka denna sidan.'
})
}
}
You can use this feature in Nuxt
export default function ({ $auth, redirect }) {
if (!$auth.hasScope('admin')) {
return redirect('/')
}
}
The scope can be anything you want e.g Consultant, Editor etc.
Check the documentation
Updated
Since you are using Laravel
You can have a role column in your user table
e.g
$table->enum('role', ['subscriber', 'admin', 'editor', 'consultant', 'writer'])->default('subscriber');
Then create a API resource, check the documentation for more
To create a user resource, run this artisan
php artisan make:resource UserResource
Then in your resource, you can have something like this
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'phone' => $this->phone,
'gender' => $this->gender,
'country' => $this->country,
'avatar' => $this->avatar,
'role' => $this->role,
];
}
Then you can import it to your controller like this
use App\Http\Resources\UserResource;
You can get the resource like this
$userdata = new UserResource(User::find(auth()->user()->id));
return response()->json(array(
'user' => $userdata,
));
In Nuxt
To do authentication in Nuxt
Install nuxt auth and axios
Using YARN : yarn add #nuxtjs/auth #nuxtjs/axios
Or using NPM: npm install #nuxtjs/auth #nuxtjs/axios
Then register them in your nuxtconfig.js
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth',
],
In your nuxtconfig.js, add this also
axios: {
baseURL: 'http://127.0.0.1:8000/api'
},
auth: {
strategies: {
local: {
endpoints: {
login: { url: '/login', method: 'post', propertyName: 'access_token' },
logout: { url: '/logout', method: 'post' },
user: { url: '/user', method: 'get', propertyName: false }
},
tokenRequired: true,
tokenType: 'Bearer',
globalToken: true
// autoFetchUser: true
}
}
}
The URL been the endpoints
Check Documentation for more
To restrict certain pages in Nuxt to Specific User.
> Create a middlweare e.g isadmin.js
Then add this
export default function ({ $auth, redirect }) {
if (!$auth.hasScope('admin')) {
return redirect('/')
}
}
Then go to the Page, add the middleware
export default {
middleware: 'isadmin'

How can i return 404 error without change url in Vue?

Question
Using Vue.js, how can i return 404 error in dynamic route without change url?
Part of my route.js (everything ok)
{
path: '/work/:id',
name: 'work',
component: () => import( './views/Work.vue' )
},
{
path: '*',
name: 'NotFound',
component: () => import( './views/NotFound.vue' )
}
Part of Work.vue component. Where i check if route param are in my static json, if not, open NotFound component before route enter
beforeRouteEnter (to, from, next) {
next(vm => {
vm.item = json.find(item => item.id == vm.$route.params.id)
if(!vm.item) {
next({name: NotFound})
}
})
}
The problem
When i try site.com/work/non-existent-id, the component "NotFound" open, but the url goes from site.com/work/non-existent-id to site.com
What I espect
site.com/work/non-existent-id open component "NotFound" and the url stays at site.com/work/non-existent-id
Example
https://v2.vuejs.org/v2/guide/something - return 404 error and stay in url
Routers are designed to do exactly what you are wanting them to not do. If you want to display some content on any route in your application, I would recommend creating a new component and maybe firing off an event to show whatever content you want.
Personally, I would think re-routing would be the way to go because this will allow the user to hit the back button in the browser to get back to where they came from, but I guess that all depends on your specific use case here.
I'm still using vue router3 and works for me without changing the url.
for axios.
beforeRouteEnter(to,from,next) {
axios
.get(`http://localhost:5000/api/product/${to.params.id}`)
.then((res) => {
next((vm) => {
vm.product = res.data;
next();
});
})
.catch((error) => {
next({ name: 'notFound', params: [to.path]});
});
}

angular 4 routing adding a component rather than replacing it

I have configured routes as follows in a sub module loaded dynamically.
I don't think the dynamic loading is causing the problem, but it may - so I have included it for reference.
dynamic load
children: [
{
path: "dashboard",
loadChildren: () => new Promise(resolve => {
(require as any).ensure([],
require => {
resolve(require("./dashboard/dashboard.module").DashboardModule);
},
"dashboard");
})
},
dashboard-routing-module
const routes: Routes = [
{
path: "",
component: ClearingDashboardComponent,
data: {
title: "Dashboard"
}
},
{
path: "logs",
component: LogDisplayComponent,
data: {
title: "Logs"
}
}
];
the landing HTML looks as follows
When navigating to the LogDisplayComponent with
const ne: NavigationExtras = {
queryParams: { ... }
};
this.router.navigate(["dashboard/logs"], ne);
A new component is being added above the HTML.
Surely each component should replace the inner HTML?
The LogDisplayComponent is above the ClearingDashboardComponent,
As I click, a new component is added each time I navigate either way?
How do I fix the route to replace the component rather than add a new one?
I am using angular 4.4.4...
Try updating your version to 5+. This issue has already been addressed by the Angular team. For more information, check these links:
https://github.com/angular/angular/issues/17261
https://github.com/angular/angular/issues/13725

Vuejs route based on payload

Im using vuerouter and want to route to a component based on payload.
{
path: '/foobar',
name: 'foobar',
component: foobar,
}
{
path: '/foobar',
name: 'foobarSuccess',
component: foobarSuccess,
query: { status: 'success' }
}
Example above, first route is step one. We do some stuff there then we go to another page and get redirected back with the payload status=succcess. How do i use the query object to route to the correct component?
You have to define your router with parameters
{
path: '/foobar',
name: 'foobar',
component: foobar,
}
{
path: '/foobar/:status',
name: 'foobarSuccess',
component: foobarSuccess,
query: { status: 'success' }
}
here status will contain like success, finally /foobar/success
based on this parameter also you can display the sccuess message
For more information you can refer the simple docs https://router.vuejs.org/en/essentials/dynamic-matching.html ,

Categories