Laravel Vue VueRouter history mode - laravel

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

Related

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 Routes with Vue Router (SPA) Not Working as normal

I am trying to create a Laravel Vue SPA application. And it seems that I cannot get the route all to function properly. Everytime I use the get('{any}') all my axios get methods call returns the index.blade.php. But if I define all routes in routes.js with more or less the same signature in my web.php (Laravel) my axios routes in getting the data works fine.
web.php
// This work but every time I do an Axios call it returns my index.blade.php
Route::get('{any}', 'SiteController')->where('any', '.*');
// This works if I define all routes, with axios fetching data normally and
// displaying the data in Vue normally
Route::get('/', 'SiteController');
Route::get('/blog', 'SiteController');
Route::get('/post/{postId?}', 'SiteController');
routes.js
const routes = [
{ path: '*', component: Home },
{
path: '/',
component: Home,
children: [
{
name: 'blog',
path: '/blog',
component: PageBlogLists,
},
{
name: 'post',
path: '/post/:page_id',
component: PageBlog,
},
],
},
];
export default new VueRouter({
base: '/',
fallback: true,
mode: 'history',
routes: routes,
});
So I finally got it working I've changed my routes to
Route::get('/{any}', 'SiteController')->where('any', '^(?!api).*$');
and move all my API requests to the api.php file
Route::resource('/posts', 'WordpressController');
router.js and axios works fine now :)
So first the root view, I do not know how does yours look like but it should be something like this
Route::get('{path}', function () {
return view('index');
})->where('path', '(.*)');
Second, you are building SPA, you should not be using web.php, you should use api.php
if you have to and really want to use web.php, you can move the any down to the bottom, and prefix all the other routes with something else.
I do not have a clear picture of the other codes you have in your hands.
But for laravel vue router, this reference helps me a lot
https://medium.com/#weehong/laravel-5-7-vue-vue-router-spa-5e07fd591981
You could give it a try. Hope this helps.

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.

laravel + vue router cannot get parameters from url

I try to get parameters from url
let's say url contains:
localhost:8000/blog?q=hello
I want to grab hello to trigger function call
What I had declare in app.js in laravel webpack:
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const router = new VueRouter({
mode: 'history',
routes: []
})
const app = new Vue({
router
});
export default app;
In blog page, I try to extract the parameter from url
new Vue ({
el: "#blog-content",
},
mounted: function() {
q = this.$route.query.q
console.log(q)
}
)
I npm run dev to compile and run the blog page it show error:
TypeError: Cannot read property 'query' of undefined
what is wrong? I am sure that Vue Router is properly installed in the application.
I think that the blog page that you use is not correct.
You recreate another Vue instance and in that case that new instance doesn't have a router passed to it. So I think that's why this.$router is undefined.
Also you don't pass the view Component to your router so it doesn't know what to look for with the specific url.
Here's your app.js file corrected
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import Blog from './views/Blog';
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/blog',
name: 'blog',
component: Blog
},
]
});
The blog view page template : views/Blog.vue
<template>
<div class="wrapper">
My blog page
</div>
</template>
<script>
export default {
data() {
return {
myvariable : ''
}
},
mounted() {
let q = this.$route.query.q;
console.log(q);
},
};
</script>
Now it should works correctly :)
Edit : Also you don't need to export the app variable in your app.js
Remove the following line export default app; at the end of the file

Laravel + Vue router - Best practice for slugs

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: ...
})

Resources