Custom Vue Component in Laravel Nova - laravel

I have a custom Vue-Component located in Laravel default path for it:
resources/js/components/MyComponent.vue
So, I installed Laravel-Nova and want to use the component inside a view partial
resources/views/vendor/nova/partials/user.blade.php
<dropdown-menu slot="menu" width="200" direction="rtl">
<my-component></my-component>
<ul class="list-reset">
<li>
...
Where should I import the Component? In other words, where should I place the:
import MyComponent from '/path/to/my/component/MyComponent.vue'
//and
Vue.component('my-component', MyComponent)
I want to do it some way I can use inside the code of the Vue Component the Nova JavaScript Helpers, like:
this.$toasted.show('It worked!', { type: 'success' })
//or
axios.get('/nova-vendor/stripe-inspector/endpoint').then(response => {
// ...
})

This is an example of a similar component:
import MyLens from './components/views/Lens';
Nova.booting((Vue, router, store) => {
router.addRoutes([{
name: 'nova-improvements',
path: '/nova-improvements',
component: require('./components/Tool'),
}])
});
Nova.booting((Vue, router, store) => {
Vue.component('lens', MyLens)
});

Related

vue router with laravel

import { createRouter, createWebHistory } from 'vue-router';
import about from './views/web/AboutPage.vue';
import support from './views/web/SupportPage.vue';
import iatiStanderd from './views/web/IatiStandard.vue';
import publishingChecklist from './views/web/PublishingChecklist.vue';
import { def } from '#vue/shared';
const routes = [
{
path: '/iati-standard',
name: 'iatiStanderd',
component: iatiStanderd,
},
{
path: '/support',
name: 'Support',
component: support,
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
I have set up routes like this.
app.use(router);
and registered like thi in app.ts file
<router-link to="/iati-standard">IATI STANDARD</router-link>
and tried to use route like this.
the url changes but desired component is not rendered. where did i go wrong?
I am using vue with laravel
you should use the name instead of the URL.
In your case:
<router-link :to="{ name: 'iatiStanderd'}"> ... </router-link>
And btw, take care for the name it is iatiStandard not iatiStanderd 🙂

Laravel/Inertia how to register globally the Link component

I'm pretty new to Inertia (I have enough experience with Laravel), so I'm writting a toy SPA application. I learn that I must use the <Link ...> component instead of <a ...> to get the SPA behaivour. Problem is that I have to import the Link component on every other component that'll use links.
So, if I have a Page, I should do something like this:
<template>
...
<Link href="/about" class="...">
About Page
</Link>
...
</template>
<script>
import { Head, Link } from "#inertiajs/inertia-vue3";
export default {
components: {
Head,
Link,
},
...
};
</script>
And this works, but I think it's quite unefficient, boresome and so to have to import the Head and Link components for every page, after all a Link is the most common element on a page other than plan text.
Here https://inertiajs.com/releases/inertia-vue3-0.5.0-2021-07-13 in the documentation says you can register Link and Head components globally, so my app.js code looks like:
require("./bootstrap");
import { createApp, h } from "vue";
import { createInertiaApp } from "#inertiajs/inertia-vue3";
import { InertiaProgress } from "#inertiajs/progress";
import { Head, Link } from "#inertiajs/inertia-vue3";
const appName =
window.document.getElementsByTagName("title")[0]?.innerText || "Laravel";
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => require(`./Pages/${name}.vue`),
setup({ el, app, props, plugin }) {
createApp({ render: () => h(app, props) })
.use(plugin)
.component("InertiaHead", Head)
.component("InertiaLink", Link)
.mixin({ methods: { route } })
.mount(el);
},
});
As the documentation says, but this does nothing. When I comment the import ... and components section on my page component. It doesn't throw an error, but it doesn't display anything, not even the text.
Any idea?
You have registered your components as "InertiaLink" and "InertiaHead". If you do this, you must also name them that way in the vue files.
app.js
vue file

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

Axios response.data return HTML instead of an object

I need help about Axios.
I develop a SPA webapp on Laravel 6 (with package SPARK) and VueJS (version 2).
On a Vue component, I want to retrieve datas from my bdd.
So, I use Axios to make a get request on an API uri.
But, when I call Axios request, data field in Response object is a HTML code.
This is my code :
routes/web.php
Route::get('/', function(){
return view('welcome');
});
Route::middleware('auth')->get('/{any?}', function (){
return view('documents');
})->where('any', '[\/\w\.-]*');
The "welcome" view is a blade page where redirect on "/login" if user is not authenticate.
Otherwise, it redirect on "/home".
The link "/home" is define on vue-router in app.js.
The other route is the unique way to display the webapp (it's a single page application).
The Vue instanciation is in "passeport" view.
resources/js/app.js
import 'es6-promise/auto'
require('spark-bootstrap');
require('./components/bootstrap');
window.Vue = require('vue');
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import VueAxios from 'vue-axios';
import axios from 'axios';
Vue.use(VueAxios, axios);
Vue.component('index', require('./components/pages/index').default);
import Dashboard from './components/pages/dashboard.vue';
...
const routes = [
{
name: 'dashboard',
path: '/home',
component: Dashboard,
},
{...}
]
const router = new VueRouter({
history: true,
mode: 'history',
routes: routes
});
var app = new Vue({
mixins: [require('spark')],
router,
});
router package is added in Vue instanciation.
it is in the same context than spark component (identify by the #spark-app element)
resources/views/documents.blade.php
#extends('spark::layouts.app')
#section('content')
<div id="app">
<index :user="user"></index>
</div>
#endsection
It is the view returned for any path.
In the spark::layout.app, there is only a div with id="spark-app" and the #yield('content').
resouces/js/components/pages/index.vue
<template>
<transition name="fade">
<Component :is="layout" :user="user">
<router-view :layout.sync="layout" :user="user"></router-view>
</Component>
</transition>
</template>
.
.
<script>
const default_layout = "default";
export default{
props: ['user'],
data(){
return{
layout: 'div',
}
},
}
</script>
It's just the vue component with the router-view configure with a layout.
resources/js/components/pages/dashboard.vue
<template>
...
</template>
<script>
import Default from './../layouts/Default.vue'
export default {
props: ['user'],
data: function () {
return {
documents: []
}
},
created() {
this.$emit('update:layout', Default);
},
mounted(){
// extract passeports's informations
this.axios.get('/api/documentslist').then(response => {
console.log(response);
this.documents= response.data.data;
});
}
}
</script>
Here, I call the documentslist API define in routes/api.php.
routes/api.php
Route::middleware('auth:api')->group(function () {
Route::get('/user', function (Request $request) {
return $request->user();
});
Route::get('/documentslist', 'DocumentController#list');
});
app/http/Controllers/DocumentController.php
...
public function list(Request $request){
return DocumentCollection(Document::all());
}
...
When I go to "/home", I verified "documents" data in Vue (or in the javascript console log), and response.data = "\r\n\r\n\r\n (...) v-if=\"notification.creator\" :src=\"notification.creator.photo_url\" class=... (10024 total length)"
But, list method in DocumentController have to return a list of documents, and not a HTML code.
Furthermore, I use Passport Laravel to unified authentication by login and the API token.
And the Axios request work in the same project without SPA structure.
I hope I'm clear in the problem explanation, and that I forget any detail to understand.
Thanks.
You can simply return like this from your controller
return response()->json(Document::all());
I suspect the API link to redirect with the SPA route (in routes/web.php, any path return the "home" view).
I try to change route in routes/web.php.
instead of :
Route::middleware('auth')->get('/{any?}', function (){
return view('home');
})->where('any', '[\/\w\.-]*');
I put this :
Route::middleware('auth')->get('/home', function (){
return view('home');
});
Like this, this route doesn't take account of all path.
And...it works !
But...it isn't what I want :(
Indeed, without the route with '/{any?}' the SPA doesn't work.
I don't understand why this method works another project in Laravel (without Spark package), and doesn't work with this project.
I don't know about laravel but this problem arises when the route you are calling is not the correct one. Do some efforts and check what route the application in eventually calling also take a look at your proxy settings.
****I am NodeJs developer not Laravel

Vue Router + Laravel: Reloading a page without a 404 and passing in a route varable

When reloading my single page application, I would like the url to load correctly instead of throwing a 404 error. Using Laravel 5.6, Vue.js 2.6, & MAMP.
I have tried the following code, however, I am loading different app.js files in the same welcome view based on what the URL is. Because of this structure,, this solution is not working:
Route::get('/{vue_capture?}', function () {
return view('welcome', ['app_path' => 'load different vuejs apps here in my routes/web.php file based on the url']);
})->where('vue_capture', '[\/\w\.-]*');
I would like to have refresh work with my vue router. Any suggestions, either having to do with my routes/web.php file or .htaccess file is appreciated.
Note: This .htaccess file configuration was not working for me (apache):
https://router.vuejs.org/guide/essentials/history-mode.html#example-server-configurations
//welcome blade
<div id="app">
<app></app>
</div>
<script src="{{ asset($app_path) }}"></script>
//app.vue
<div class="container-fluid px-0">
<router-view/>
</div>
Well, as far I can see, your approach was good. You are capturing all GET requests, and passing them to your Blade view.
My suggestion:
Cleaner route:
Route::get('/{any}', 'YourController#index')->where('any', '.*');
Your app.js (main JS file should look something like this):
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import App from './views/App'
import About from './views/About'
import Home from './views/Home'
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About,
},
],
});
const app = new Vue({
el: '#app',
components: { App },
router,
});
With all this configuration and your router-view, you should be fine.

Resources