Laravel + SPA VueJs not giving error for unknown component - laravel

<template>
<div>
<test-component />
</div>
</template>
<script>
//import TestComponent from '../path-to-components/TestComponent';
export default {
name: 'SomeRandomComponent',
components: {
TestComponent,
}
}
</script>
Expected Behaviour:
The application should give some console error if there is a problem with the imports or anything else similar to this.
Current Behaviour:
The page get blank in the browser and there is no error in console even if the import statement is commented out.
Code for reference
app.js
import Vue from 'vue';
import router from '~/router';
import App from '~/components/App';
new Vue({
router,
...App
})
router.js
export default [
{ path: '/some-path', name: 'testing', component: import( `~/pages/path-to-component`).then(m => m.default || m) },
]
App.vue
<template>
<div id="app">
<loading ref="loading" />
<transition name="page" mode="out-in">
<component :is="layout" v-if="layout" />
</transition>
</div>
</template>
<script>
import Loading from './Loading'
// Load layout components dynamically.
const requireContext = require.context('~/layouts', false, /.*\.vue$/)
const layouts = requireContext.keys()
.map(file =>
[file.replace(/(^.\/)|(\.vue$)/g, ''), requireContext(file)]
)
.reduce((components, [name, component]) => {
components[name] = component.default || component
return components
}, {})
export default {
el: '#app',
components: {
Loading
},
data: () => ({
layout: null,
defaultLayout: 'default'
}),
metaInfo () {
const { appName } = window.config
return {
title: appName,
titleTemplate: `%s · ${appName}`
}
},
mounted () {
this.$loading = this.$refs.loading
},
methods: {
/**
* Set the application layout.
*
* #param {String} layout
*/
setLayout (layout) {
if (!layout || !layouts[layout]) {
layout = this.defaultLayout
}
this.layout = layouts[layout]
}
}
}
</script>

I am assuming that you are using Vue2 since Vue3 is in beta.
The first problem I see with your code, is that your <div id="app"> is inside a Vue component.
Declarative Rendering
What happening is that everything is compile, but you are trying to render Vue inside a component that does not exist.
Instead, create a div element inside the html or blade.php file that is loaded by the client. For my part, I use a blade layout like this:
//resources/views/layouts/app.blade.php
...
</head>
<body>
<div id="app" v-cloak> //This is plain loaded when client render views, then, when script will initiate, Vue will be able to access everything inside this.
<navbar v-bind:core="core"></navbar> //There is my navbar which is a Vue component.
<div class="boxed">
<div id="content-container">
#yield('content') //Blade component are injected there. since it's inside the <div id="app">, thoses component can include Vue directive/component.
</div>
...
Another thing that seems a problem is that you are initiating Vue inside a Vue component. Things are that Vue is a package and compiled into javascript in the end. But, to make all the magic happen, you need to have somwhere to initiate all this. In that case, your App.js file should look something like this:
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
/**
* The following block of code may be used to automatically register your
* Vue components. It will recursively scan this directory for the Vue
* components and automatically register them with their "basename".
*
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
*/
// const files = require.context('./', true, /\.vue$/i)
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
const app = new Vue({
el: '#app',
});
This file is the one created by default by laravel for Vue template on fresh Laravel 8 install.
The difference between import and require is that import create a promise.
You don't want a promise there, because you want that file to be execute at the moment the client will begin to render your page.
Following thoses recommendation, I think you will be able to get your app working quickly and Vue will start logging error into your console.

Related

Vue Component not showing text when called from blade.php file

I have a basic vue 2.6.11 component that lives in a laravel 6 application. It lives at resources/js/components. I create a basic component and then in my app.js file I have vue imported and I define my vue component. Then in my app.blade.php I use the vue component but the text within my <template><div>Text here</div></template> does not appear on the screen. The <h1> text appears but not the vue component text. I looked at other posts but the vue versions other questions on here use are 2-3 years too old and don't apply. Any help is appreciated, thanks.
TableDraggable.vue
<template>
<div>
<h1>Test Text</h1>
</div>
</template>
<script>
export default {
mounted() {
console.log('this component has been mounted');
}
}
</script>
What I am using in my app.blade.php file
<h1>This is a test to see if VUE is working</h1>
<table-draggable></table-draggable>
app.js snippet
//Bring in VUE and vue draggable
window.Vue = require('vue');
import VueDraggable from 'vuedraggable';
Vue.component('table-draggable', require('./components/TableDraggable'));
In app.js try the following:
...
window.Vue = require('vue');
import VueDraggable from 'vuedraggable';
Vue.use(VueDraggable);
import TableDraggable from './components/TableDraggable';
Vue.component('table-draggable', TableDraggable);
const app = new Vue({
el: '#app',
data() {
return {};
},
});
...
Then in some parent element of where you are using your component, make sure it has an id of app. eg:
<div id="app">
<h1>This is a test to see if VUE is working</h1>
<table-draggable></table-draggable>
</div>
This is a basic example of getting vue working on your site, and not necessarily the best way to be structuring your assets depending on your needs. The biggest considerations about how to structure these are how bulky your assets will become if you include everything in app.js.

Laravel Nova - Custom Card w/ Package

I created a custom card in order to use Chartkick. This custom card will have a select dropdown which will make an Axios request to get data from an API and display it in the chart though my issue is the chart will not display even with hard-coded dummy data as can be seen below:
<template>
<card class="flex flex-col items-center justify-center">
<span>Ben</span>
<line-chart class="lcs" :data="chart_data"></line-chart>
</card>
</template>
<script>
import Vue from "vue";
import Chartkick from "vue-chartkick";
import Chart from "chart.js";
Vue.use(Chartkick.use(Chart));
export default {
props: ["card"],
data() {
return {
chart_data: {
"2017-05-13": 2,
"2017-05-14": 5
}
};
}
};
</script>
<style scoped>
.flex {
min-height: 950px;
}
</style>
The card is working and displaying on the dashboard. I simply placed span tags and output a name to confirm this as can be seen here:
I played with the CSS of the box to make sure the chart wasn't being hidden as can be seen from the changed shape.
I can't seem to get the chart to display and am unsure of what is being done wrong.
Your component is not rendered in the page, you should compile your assets and register them in the NovaServiceProvider
npm run dev
And in the boot function in your Laravel app
use Laravel\Nova\Events\ServingNova;
class NovaServiceProvider extends NovaApplicationServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
$this->app->booted(function () {
$this->routes();
});
Nova::serving(function (ServingNova $event) {
Nova::script('{{ component }}', __DIR__.'/../dist/js/card.js');
});
}
From the Docs

Importing a JavaScript class into a Vue single file component using Laravel Mix

I'm writing a Vue single page component in my project which is bundled using Laravel Mix. I want to extract some logic out into its own class so that it can be easily re-used across other components (but this isn't logic that should be a Vue component itself).
I made a new class and put it in TimeRangeConverter.js, in the same directory as my Vue component.
export default class TimeRangeConverter {
static getFromTimestamp() {
return 1;
}
}
And in my component, I'm importing it as I think I normally would:
<template>
<div>
Example component
</div>
</template>
<script>
import './TimeRangeConverter';
export default {
mounted() {
console.log(TimeRangeConverter.getToTimestamp());
}
}
</script>
However Vue is throwing an error saying ReferenceError: TimeRangeConverter is not defined.
I'm using the default webpack.mix.js config file that comes with Laravel 5.7:
mix.js('resources/js/app.js', 'public/js');
And in my main app.js file I'm automatically including Vue components with:
const files = require.context('./', true, /\.vue$/i);
files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default));
What's the correct way to import this class into a Vue component for usage?
You should import your class inside your component code using the following syntax :
import TimeRangeConverter from './TimeRangeConverter';

Laravel + VueJS - Component doesn't displayed

I'm trying to add VueJS in my Laravel app, but my first component is not displayed on my page.
As you can see on the source page, we can see the component "login".
And this is the associate code:
<template>
<p>Coucou je suis un élément Vue.JS</p>
</template>
<script>
export default {
name: "login"
}
</script>
<style scoped>
</style>
It's just a simple component that display a string.
Here you have the app.js
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('example-component', require('./components/ExampleComponent.vue'));
Vue.component('login', require('./components/Auth/Login.vue'));
const app = new Vue({
el: '#app'
});
But my problem is that nothing appears on the html page :/ It's completely blank...
If someone could explain what's wrong, it will be so appreciate. Thank in advance.
Well, i found my mistake. I forget to add theses two lines :
<script src="{{ asset('js/manifest.js') }}"></script>
<script src="{{ asset('js/vendor.js') }}"></script>

Laravel and VueJS with blade templates

The new laravel comes with a built-in VueJs. But what I need is one instance of vuejs binded to body tag for the whole app. How can I achieve this ? Is there a way of binding vue directly on body element, even though its not recommended ? The purpose is only using vue to make an API calls for certain parts of my app, but I need vue to be available globally and without binding to specific element, which will destroy my current app
Update Code:
default layout - laravel
...
</head>
<body id="app" class="{{isActiveRoute('home')}}">
...
</body>
resources/assets/app.js
require('./bootstrap');
window.Vue = require('vue');
Vue.component('example', require('./components/Example.vue'));
const app = new Vue({
el: '#app',
components: ['example'],
data: {
name: 'test'
},
methods: {
addToCart() {
console.log('add to cart');
}
},

Resources