Laravel + Vue router - Best practice for slugs - laravel

I have a laravel + vue app. I've created a vue spa application for a particular page called shop. In this shop, I have 3 sub pages which is about, products and contact.
routes.php
Route::get('/shop/{slug}/{vue_capture?}', 'ShopController#show')->where('vue_capture', '[\/\w\.-]*');
vue-router.js
export const routes = [
{ path: '/', component: Home, name: 'home',
children: [
{
path: '/',
name: 'about',
component: About
},
{
path: '/products',
name: 'products',
component: Product
},
{
path: '/contact',
name: 'contact',
component: Contact
}
]
},
];
So for example I go to domain.com/shop/joe-shop, what is the best practice to extract the slug and use it in my vue application so I can make http requests with slug parameter to server? Thank you
note: I'm also using vuex state management in my app

var slug = window.location.pathname.replace(/^\/shop\/([^\/]+)(?:\/.*)?/i,'$1');
Note:
With your current set-up, you would need to set the base property in your vue-router config to behave properly.
new Router({
base: window.location.pathname.replace(/^(\/shop\/[^\/]+).*/i,'$1'),
mode: 'history',
routes: ...
})

Related

Refreshing page while changing routes, Vue.js spring SPA

I'm trying to create aplication using Vue.js and Spring boot. After switching to a different route using Vue routing my page reloads. I'm using this pice of code to forward to my client side route.
#Controller
class FrontController {
#GetMapping("/**/{path:[^\\.]*}")
fun redirect(#PathVariable path: String): String {
return "forward:/index.html"
}
}
index.js
const routes = [
{
path: '/sad',
name: 'AdminDashboard',
component: AdminDashboard
},
{
path: '/',
name: 'UserList',
component: UserList
},
{
path: '/role/all',
name: 'RoleList',
component: RoleList
},
{
path: '/course/all',
name: 'CourseList',
component: CourseList
},
{
path: '/category/all',
name: 'CategoryList',
component: CategoryList
}
]
const router = new VueRouter({
mode: 'history',
routes
})
export default router
Here is a gif to show my problem: https://imgur.com/zv0CIzv. So ye I'm trying to get rid off that flashing when switching on different pages. It works fine on Microsoft Edge, but not on Chrome and Firefox.
fun redirect(#PathVariable path: String, e:event): String {
e.preventDefault();
return "forward:/index.html"
}

Laravel Vue VueRouter history mode

I'm building an e-commerce project with laravel, vue and vue router
I want to use vue router with history mode but it cause me trouble.
Here is my code
new Vue({
el: '#app',
router: new VueRouter({
mode: 'history',
routes
})
});
Here is my route in web.php which have locale middleware
Route::group(['prefix' => '{locale}', 'where' => ['locale' => '[a-zA-Z]{2}'], 'middleware' => 'setlocale'], function () {
Route::view('/{path?}', ('layouts.app'))->where('path', '.*');
});
Here is my route with vue router
export const routes = [
{
path: '/',
component: require('./components/Page/HomePage').default,
},
{
path: '/product',
component: require('./components/Page/Product/ProductPage').default,
},
];
I need my url to be
http://localhost/en
instead of (with the hashtag)
http://localhost/en#/
After using history mode, i successfully remove the hashtag. But, the router link of other will remove my locale in my url
http://localhost/product
I don't know what to do now with it.
Please help~ Thanks.
Update 19 Mar 2020
You need to set the base value to tell Vue Router what the base URL of your application is. In your case you can set it dynamically using the locale value.
For example, in your Blade template you could have the following script to set the locale value on the JavaScript window object:
<script>
window._locale = "{{ app()->getLocale() }}";
</script>
And then you can set the base value to the locale when creating your router:
router: new VueRouter({
mode: 'history',
base: `/${window._locale}/`,
routes
})
Very simple way is too Accept the locale in Vue router too. So your route would be like this:
export const routes = [
{
path: '/:locale',
children: [
{
path: '',
component: require('./components/Page/HomePage').default,
},
{
path: 'product',
component: require('./components/Page/Product/ProductPage').default,
},
]
}
];
just be sure for children route dont put '/' in begining because its remove locale

On refresh vuejs template is not working and I get just json Data, Vuejs and Laravel

I have a route where when I refresh the page I get only the JSON info for that page. (only on refresh F5). The rest of the routes are ok. I am not sure what I am doing wrong.
web.php
Route::get('/persons', 'MyController#index');
Route::post('/record/{personId?}', 'MyController#create'); // this is the one that don't work on refresh
Route::get('/record/{id}', 'MyController#getRecord');
Route::delete('/record/{id}', 'MyController#destroy');
Route::get('/lookups', 'LkpController#index');
Route::post('/validate', 'MyController#getValidation');
//Routes for VueJs
Route::get('/{any}', function () {
return view('welcome');
})->where('any','^(?!api).*$')->name('home');
router.js
const routes = [
{
path: "/",
name: "Home",
component: Home,
meta: { requiresAuth: true }
},
{
path: "/record",
name: "Record",
component: Record,
meta: { requiresAuth: true }
},
{
path: "/record/:id",
name: "View Record",
component: require ('./components/AddPerson').default,
meta: { requiresAuth: true }
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
The problem is that you are putting all your routes in web.php, and you have the same routes for your Vue SPA as your Laravel application.
You should put your API routes in your web/api.php file that way they will be automatically prefixed with the 'api' route.
The route that is returning JSON data is not the one you pointed out, it is the next one:
Route::get('/record/{id}', 'MyController#getRecord'); // this is the one that don't work on refresh
This is because your Vue router is pointing to the exact same route:
{
path: "/record/:id",
name: "View Record",
component: require ('./components/AddPerson').default,
meta: { requiresAuth: true }
}
Both routes point to yourwebsite.com/record/{id}, but on refresh you make a brand new request to your Laravel application, that means your not in your Vue application anymore and your browser will load whatever Laravel will tell them first, in this case it will be the first route in the routes/web.php file:
Route::get('/record/{id}', 'MyController#getRecord');
Edit: This is how you should do it if you cannot use API routes due to authentication:
You must make sure that your don't have duplicate routes between your Vue router and your Laravel routes, you can just prefix them with something that makes sense to you.
Route::prefix('prefix')->group(function () {
Route::get('/persons', 'MyController#index');
Route::post('/record/{personId?}', 'MyController#create');
Route::get('/record/{id}', 'MyController#getRecord');
Route::delete('/record/{id}', 'MyController#destroy');
Route::get('/lookups', 'LkpController#index');
Route::post('/validate', 'MyController#getValidation');
});
//Routes for VueJs
Route::get('/{any}', function () {
return view('welcome');
})->where('any','^(?!api).*$')->name('home');
In this example, the route you are having trouble with will now be prefixed with 'prefix' yourwebsite.com/prefix/record/{id}, you can change it to whatever you need it to be.

Laravel middleware on a VueJS route

I have a VueJS route in my SPA application. I would like to apply a Laravel Middleware to a route (the auth middleware, in this case).
Actually, I have try this:
app.js
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: require('./views/Home').default,
},
{
path: '/hello',
name: 'hello',
component: require('./views/Hello').default,
},
],
});
routes/web.php
Route::get('/hello', 'HomeController#home')->middleware('auth');
Route::get('/{any}', 'FrontendController#index')->where('any', '.*');
In this code, I have try to link the auth middleware to the route /hello, but it don't work. What is the best way to do that ?
Thanks.
I have not worked with Laravel for about 6 years, but with Vue. I believe that this is because you never get into your Laravel route, since the Vue app is assembled, and it is therefore fully available in the browser.
It would be different if you loaded the component in the Vue router via lazy load.
component: () => import(/* webpackChunkName: "hello" */ './views/helo.vue')
I don't know exactly how that works with Laravel. I use the Vue CLI tool. Hope this could help you a little.

Skip login screen while opening a vue route link

I am using laravel and vue js in my app. All the vue routes ask for a login when opened as i am using laravel auth. I want to create some routes that should be accessable without a user to be logged in. In other words I want some route that can be accessed by guest user as well. But at the moment all routes require user to be authenticated. These are my routes
const routes = [
{ path: '/dashboard_admin', component: require('./components/dashboard.vue').default},
{ path: '/ongoing_events_admin', component: require('./components/events.vue').default } ,
{ path: '/courses_admin', component: require('./components/courses.vue').default},
{ path: '/front_images_admin', component: require('./components/front_images.vue').default},
{ path: '/news_admin', component: require('./components/news.vue').default},
{ path: '/main', component: require('./components/main_view/index_view_general.vue') ,
name: 'index',
props: true ,
beforeEnter:DontrequireLogin
},
//general vue
// { path: '/', component: require('./components/main_view/index_view_general.vue').default},
]
const router = new VueRouter({
mode: 'history',
routes // short for `routes: routes`
})
const app = new Vue({
el: '#app',
router
});
These are my routes. I want some of these routes that can be accessed by guest user as well but at the moment all routes require user to be logged in.
So you need to do this meta's, for more about this you can read from its official documentation Route Meta
Let me explain litle bit what meta's do .
in meta you define a bolean object which indicate , this route is for authenticated or users or for guest user. let see below example.
i have authenticated route, only for authenticated users.
{path: '/account-setting',component:accountSetting,meta:{auth:true}},
so i pass auth object in meta and decide in route.beforeach what to do with this route.
so same a normal route
{path: '/about',component:about}
in this i give no meta, which means its for all user.
read the documentation to know how to use it.

Resources