Displaying ziggy packeg wrong - laravel

I installed the package tightenco/ziggy, set it up as in the documentation, everything works.
But the template displays the entire list of addresses as in the screenshot
Please tell me where I went wrong
<head>
#routes
#vite('resources/js/app.js')
#inertiaHead
</head>
<body>
#inertia
</body>
<Link :href="route('listing.show', listing.id)">
<listingAddress :listing="listing" />
</Link>
app.js
import { ZiggyVue } from 'ziggy'
import { Ziggy } from './ziggy';
vite.config
.use(ZiggyVue, Ziggy)
resolve: {
alias: {
ziggy: path.resolve('/vendor/tightenco/ziggy/dist/vue.es.js')
},
},

As stated on the documentation you can exclude certain routes or include the route you want to expose to the client .
Ziggy supports filtering the routes it makes available to your JavaScript, which is great if you have certain routes that you don't want to be included and visible in the source of the response sent back to clients. Filtering routes is optional—by default, Ziggy includes all your application's named routes.
To set up basic route filtering, create a config file in your Laravel
app at config/ziggy.php and define either an only or except setting as
an array of route name patterns.
// config/ziggy.php
return [
'except' => ['_debugbar.*', '_ignition.*',],
];

Related

Laravel vue.js 2 response view won't output parameters

I am new to vue.js and recently been assigned a project to learn it and refactor old code to vue.js like some of the existing pages already have been and I am having some issues. vue2
My question:
I have a get request with a controller that has a response something like this:
return Response::view('somebladefile', ['title' => 'some_title']);
Within the blade file I include a js file which will be responsible for vue
<script src="{{ cdnMix('somefile.js') }}"></script>
somefile.js contents:
const IndexPage = Vue.component('indexpage',require('./somepath/IndexPage.vue').default);
window.indexPageInstance = new IndexPage().$mount('#vuecontainerid');
So now within IndexPage.vue i would like to access variable 'title' that I passed with the response to my blade file originally. What would be the best way one would go about it? Tried few ways I found on YT/Google but without success, this is my code currently, any pointers would be appreciated, thanks!
<template>
<HeaderComponent></HeaderComponent>
</template>
<script>
const HeaderComponent = require('./somepath/HeaderComponent.vue').default;
export default {
name: 'indexpage',
props: ['data'],
components: {
'HeaderComponent': HeaderComponent,
},
data: function() {
return {
// why doesn't it work!!: '',
}
},
mounted: function() {
console.log(this.data);
}
}
</script>
Vue works, but I can't seem to be able to access 'title' variable.
Also I would like to be able to access 'title' within other components like the HeaderComponent I have within indexpage

Vue components in Inertia with Laravel seems to load twice

With a newly created Laravel with Inertia and Vue project, I have an error that it runs code inside my vue components twice.
For a simple test demo, I have a Test.vue, with this code
<template>
<div>
TEST
</div>
</template>
<script>
export default {
name: "Test",
mounted() {
console.log('test')
}
}
</script>
<style scoped>
</style>
Route in web.php:
Route::get('/test', array(App\Http\Controllers\DashboardController::class, 'test'));
In controller:
public function test(): Response
{
return Inertia::render('Test');
}
When I go to the route /test, it echoes out 'test' twice on mounted in my console. In more advanced components which calls APIs and such, also calls them twice.
I suspect maybe my project is set up wrongly, in app.blade.php or app.js but cannot figure it out.
I followed the guides on https://inertiajs.com/server-side-setup and https://inertiajs.com/client-side-setup to set this up.
My source code is here: https://github.com/ekstremedia/laravel-inertia
Edit: It seems to only echo out twice in the first component I load. If I in that component link to another component, and go there, it doesn't load that twice.
I found that this is solved by modifying your app.js file in your resources directory thus:
import Vue from 'vue'
import { App as InertiaApp, plugin as InertiaPlugin } from '#inertiajs/inertia-vue'
Vue.use(InertiaPlugin)
new Vue({
render: (h) =>
h(InertiaApp, {
props: {
initialPage: JSON.parse(app.dataset.page),
resolveComponent: (name) => require(`./Pages/${name}`).default,
},
}),
}).$mount(app);
Your problem seems to have been in how you initialized your inertia app.

Laravel and Inertia create route inside Vue

I installed Laravel with Inertia. And I got this inside resources/js/app.js:
require('./bootstrap');
// Import modules...
import { createApp, h } from 'vue';
import { App as InertiaApp, plugin as InertiaPlugin } from '#inertiajs/inertia-vue3';
import { InertiaProgress } from '#inertiajs/progress';
const el = document.getElementById('app');
createApp({
render: () =>
h(InertiaApp, {
initialPage: JSON.parse(el.dataset.page),
resolveComponent: (name) => require(`./Pages/${name}`).default,
}),
})
.mixin({ methods: { route } })
.mixin(require('./translation'))
.use(InertiaPlugin)
.mount(el);
InertiaProgress.init({ color: '#4B5563' });
As you may see there is .mixin({ methods: { route } }). I can use this.route('name.of.route') to generate named route from ˙routes` folder.
I want to modify route method to add prefix by default every time route is generated. How do I adjust Inerta's route method.
With Inertia all routing is defined server-side. Meaning you don't
need Vue Router or React Router. Simply create routes using your
server-side framework of choice.
You can read more about it here (https://inertiajs.com/routing#top)
You've got all the routes available on your javascript installed because of ziggy library. It provides a JavaScript route() helper function that works like Laravel's, making it easy to use your Laravel named routes in JavaScript.
To modify or add prefix to the URL, you'll have to do it from the backend(Laravel) using Middleware or Route Groups, because Ziggy doesn't create URL, it just provides the URL that you define in your Laravel's web.php file in your Javascript.
That's why you have #routes in your root blade file. If you remove that, this.routes or this.$routes won't be available.
E.g.
Route::group(['prefix' => 'u'], function () {
Route::inertia('/dashboard', 'Dashboard')->name('dashboard');
});
This means this URL will be available at /u/dashboard and you can access it with Javascript as this.route('dashboard');
Or read more on the ziggy package to give you the desired result

Is there an easy way to make SPA auth in Vue.js + Laravel without using JWT?

I am building an App in Laravel + Vue.js. I have a bunch of views ready I wanted to make it SPA, looking it up I found out about JWT authentication, but I had a lot of problems implementing it and I find it way too complicated (you have to change too many things to the code, make a lot of promises and stuff I still don't understand).
When you first build an app in Laravel you execute a command in console which creates you a Login/Register/Logout module automatically, is there a way I can implement that with Vue (using the router, axios or whatever) so I don't have to use JWT?
Yes there is, It will mean creating an additional column in your users table where you will save user tokens. Although is is not optimal.
Because these tokens are required for performing GET, POST, CREATE and DELETE Requests, you will have to append the token as a second parameter for all api requests.
Below shows a sample code
For my auth, I have used the defaul auth that Laravel ships with which means a user is by default, redirected to home.blade.php file, that looks like this
#extends('layouts.app')
#section('content')
<App :user='{{ auth()->user() }}'></App>
<!-- The :user has to be accepted as a prop in the App component -->
#endsection
In the App.vue file, which is the layout of your SPA you can do somthing like this
<template>
<div>
<router-view> </router-view> <!-- for all other components -->
</div>
</template>
<script>
export default {
name: "App",
props: [
'user'
],
components:{
},
created(){
window.axios.interceptors.request.use(
(config) => {
if(config.method === 'get'){
config.url = config.url + '?api_token='+ this.user.api_token;
}else{
config.data = {
...config.data,
api_token: this.user.api_token
}
}
return config;
}
)
}
//to set the api_token globally such that it does not need to be typed in eveywhere, we do it whe the component is created/mounted
//let me know if it helps
}
</script>
<style>
</style>
For your logout,
<router-link to="/logout"> Logout </router-link>
//in your Logout component, you can have something like this
<template>
<div>
</div>
</template>
<script>
export default {
name: 'Logout',
created(){
axios.post('/logout', {})
.finally(err => {
window.location = '/login';
})
}
}
</script>

Deploy Vue SPA with Laravel Backend

I am trying to figure out how I will deploy a Vue SPA with a Laravel backend on Ubuntu on DigitalOcean
I am currently able to deploy Laravel apps on Digital Ocean with no problem at all. My new challenge is that I am creating an SPA with the Vue-Webpack template and using a standalone Laravel app as backend.
I am not sure how I will deploy this and structure my folders on Ubuntu.
one way is to keep your projects in /var/www/ side by side in two folders(laravel-api and vue-app). another way is placing your app contents inside laravel-app's resources folder. configure nginx or apache to serve the laravel api backend only.
see http://vuejs-templates.github.io/webpack/backend.html
update config/index.js
var path = require('path')
module.exports = {
build: {
index: path.resolve(__dirname, 'dist/index.html'),
assetsRoot: path.resolve(__dirname, 'dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true
},
dev: {
port: 8080,
proxyTable: {}
}
}
from the docs
build.index
Must be an absolute path on your local file system.
This is where the index.html (with injected asset URLs) will be
generated.
If you are using this template with a backend-framework, you can edit
index.html accordingly and point this path to a view file rendered by
your backend app, e.g. app/views/layouts/application.html.erb for a
Rails app, or resources/views/index.blade.php for a Laravel app.
build.assetsRoot
Must be an absolute path on your local file system.
This should point to the root directory that contains all the static
assets for your app. For example, public/ for both Rails/Laravel.
What you should do is serve your main index file through Laravel routes or some other method of serving. lets say you have home.blade.php as index file
1 - show application entry point
routes.php / web.php
Route::get('/', function() {
return view('home');
});
this index file should contain the app element. then you should use vue-router for navigation which will add # after index url.
Here is how to configure javacript part
2 - Install and Import VueRouter to /resources/assets/js/bootstrap.js
3 - Use Vue router with Vue ( Vue.use(VueRouter);)
bootstrap.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import axios from 'axios';
window.Vue = Vue;
Vue.use(VueRouter);
window.axios = axios;
window.axios.defaults.headers.common = {
'X-Requested-With': 'XMLHttpRequest'
};
4 - Create /resources/assets/js/routes.js file
5 - Import vue router
6 - define routes
7 - Export routes
routes.js
import VueRouter from 'vue-router';
let routes = [
{
path: '/',
component: require('./views/Home')
},
{
path: '/another',
component: require('./views/Another')
}
];
export default new VueRouter({
routes
})
8 - Create /resources/assets/js/ app.js file which would be the javascript main app
9- require the bootstrap.js and Import routes.js file we created
10 - Use it set router: router (as we are using ES6 just router as defined below would be considered as router:router)
11 - Thats the new Vue app there
app.js
require('./bootstrap');
import router from './routes';
new Vue({
el: '#app',
router
//app works go here
});
12 - Use app.js in the home.blade.php
13 - Add router links
14 - Add router view
home.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My App</title>
</head>
<body>
<div id="app">
<section class="section">
<div class="container">
<nav class="tabs is-boxed">
<div class="container">
<ul>
<router-link tag="li" to="/" exact>
<a>Home</a>
</router-link>
<router-link tag="li" to="/another">
<a>Another</a>
</router-link>
</ul>
</div>
</nav>
<router-view></router-view>
</div>
</section>
</div>
<script src="/js/app.js"></script>
</body>
</html>
15 - Remember to run webpack.
Good luck
I am assuming you have two folders for your project: client where your vue.js code goes in, and server where your backend code lives.
The short answer
Just copy the SPA build files (located in client/dist folder by default) into your server/public folder and deploy it (The same thing is true with express for Node.js).
But you can do it better
Surely you want to avoid the manual work of copying static files from client/dist to server/public on every build you do. This is easy, all you need is just changing the build folder in your client/config/index.js and make it your server/public instead of the default client/dist.
client/config/index.js:
build: {
// change "../dist" to "../../server/public" in both rules
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
}
This is the recommended way to do it as described in the webpack template guide.
Check out my new project Laravue-SPA. It's a framework that pulls together Laravel, Vue.js and Vuetify to create a single page application.
It's brand new and still pre alpha release but I'll be happy to provide support and fix bugs as they're discovered!
Plus it will introduce you to the concepts needed to create an SPA even if you go off in your own direction.

Resources