Laravel - Vue component rendering twice because of app.js - laravel

I have a Laravel 7 project and installed bootstrap as well as the ui vue auth package. I'm trying to modify the home (home.blade.php) which extends app.blade.php but I've found that somehow the <div id="app"> in app.blade.php is rendering twice. I put a script tag with a console.log() at the bottom of app.blade.php just before the div tag closes and it outputs twice. However, when I put the script tag outside this div it behaves as it should and it only outputs once.
I found out that this is due to a script tag in the head of app.blade.php:
<script src="{{ asset('js/app.js') }}" defer></script>
When I commented that line, everything worked fine! So, my questions are:
Why is this script tag here? Why does it make everything run twice? Do I really need it? Will I encounter problems in the future by not having it?
webpack.mix.js:
const mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');
resources/js/app.js:
require('./bootstrap');
window.Vue = require('vue');
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
const app = new Vue({
el: '#app',
});
app.blade.php:
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<!-- Fonts -->
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<!-- Icons -->
<script src="https://kit.fontawesome.com/36a988e261.js" crossorigin="anonymous"></script>
</head>
<body>
<div id="app">
<script type="application/javascript">console.log('app')</script>
</div>
</body>
</html>
Edit: Since it's been a few hours and no answers I decided to set up a repo in case anyone wants to see first-hand what the problem is.

I faced same problem, in my case it was due to some iframes in the page targetting # src url. I realized it was written several times that message in the console :
[Vue devtools message in console][1]
So, I created a new special route
Route::get('/frame', [PagesController::class, 'frame'])->name('frame');
which return an empty string like
/**
* Used for iframes to override dowloadinf twice page content
*/
public function frame() {
return "";
}
And it solved my problem. Maybe it can be the same for all ressources fetched at "#"
.
[1]: https://i.stack.imgur.com/Z55BX.png

I found out this is because of having script tags outside of a Vue component. I deleted the script tag in app.blade.php and put the ExampleComponent that comes when installing vue with laravel which has a console.log inside the mounted() method and it only gets called once.
Still, I have no idea as to why this happens. If someone could shed light into this matter that would be awesome. Maybe I'll post another question with this new insight.

Related

laravel not rendering js components

the same questions already asked here but answer do not resolve my problem
1. Laravel: vue components not rendering
2. Vue component not showing in laravel
this my home.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Full stack blog</title>
<style>
</style>
</head>
<body>
<div id="app">
<mainapp></mainapp> #this one show as read
</div>
</body>
<script src="{{mix('/js/app.js')}}"></script>
</html>
this is my app.js
require('./bootstrap');
window.Vue = require('vue')
Vue.component('mainapp',require('./components.vue/mainapp.vue').default)
const app = new Vue({
el: '#app'
})
and this my mainapp.vue
<template>
<div>
<h1>this is the frist components</h1>
</div>
</template>
and
laravel : 8
Vue: 2.6.12
when I run npm run watch and php artisan serve
then I check in 127.0.0.1/8000
I can see this
You are running Vue in development mode. Make sure to turn on
production mode when deploying for production. See more tips at
https://vuejs.org/guide/deployment.html
but it does not render how can I solve this?

CSS loading slow and causing temporary weird formatting on Laravel app with Blade and Vue

I have a Laravel app that uses a tiny bit of Vue code in the blade templates. There's a problem navigating from view to view, almost every time there's a brief delay before the CSS is loaded where the raw text of the page shows without any formatting. It shows for about 1/2 a second and then the CSS kicks in and it looks correct. I can't find any reason for this, I tried changing the mix('css/app.css') etc so that it's not having to reload every time, but I can't figure out how to fix it.
I'm not sure if Vue is somehow delaying the css from loading? Any ideas what it could be? I'll paste the top section of the blade template below. I just upgraded to Laravel 8 but the same was happening with Laravel 7.
Thanks for your help!
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="title" content="Pono Admin">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Admin</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght#300;400;700&display=swap" rel="stylesheet">
<!-- Styles -->
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
<link href="{{ mix('css/admin.css') }}" rel="stylesheet">
#hasSection('style')
#yield('style')
#endif
<!-- Scripts -->
#hasSection('script')
#yield('script')
#else
<script>
var vmMixinsAdmin = '';
</script>
#endif
<script src="{{ mix('/js/app.js') }}" defer></script>
<script>
var vmMixinsApp = '';
let vroundedBtn = false;
let vunreadNotificationCount = {{ auth()->user()->unreadNotifications()->count() }};
</script>
</head>
<body>
<div id="vm">
<main id="app-main" class="container-fluid px-0">
etc
Someone had something similar and decided to show an overlay on foreground and hide it after the page has loaded. I'm not sure that it's the best solution but it could help:
Force browsers to load CSS before showing the page

Import vue js file to laravel

I used these vue js files to build my form in Larval.
When I call these files in Larval I get a blank page.
The structure of my files is as follows:
And the contents of app.js file is as follow:
import Vue from "vue"
import App from "./components/App.vue"
import store from "./components/store"
import VeeValidate from "vee-validate"
Vue.use(VeeValidate);
import "./components/directives"
Vue.config.productionTip = false;
new Vue({
store,
render: h => h(App)
}).$mount("#app");
Of course, I get the below warning when I run nmp run watch's command.
WARNING in ./resources/js/app.js 5:8-19 "export 'default' (imported as
'VeeValidate') was not found in 'vee-validate' # multi
./resources/js/app.js ./resources/sass/app.scss
My question is: How to import external vue js files to laravel project?
First thing you need to include app.js to your blade file like this
<script src="{{asset('js/app.js')}}"></script>
after that if you want to use vue js components in you blade app you need to define them in your app.js like this:
Vue.component('home', require('path to your component').default);
and in your blade under div #idd add your tag <home></home>
use src="{{ mix('js/app.js') }}"
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" value="{{ csrf_token() }}" />
<title>VueJS CRUD Operations in Laravel</title>
<link href="{{ mix('css/app.css') }}" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="app">
</div>
<script src="{{ mix('js/app.js') }}" type="text/javascript"></script>
</body>
</html>

Vue+laravel+apache not redirecting properly

Iḿ trying to run vue+laravel project without php artisan serve but when I acces localhost/project/public I see a blank page with this content only:
<head>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?
family=Roboto:100,300,400,500,700,900"><link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/#mdi/font#latest/css/materialdesignicons.min.css">
</head>
<body></body>
Despite this, when I acces localhost/project/public/any I see my default not found vue page so when I click go home button I can access my entire project without problems. Anyone can help to redirect properly to / route when going to localhost/project/public.
Note: It works fine with php artisan serve and I'm trying this because I want to run my project in a ec2 instance but facing same probleme even with a virtual host to redirect to /project/public from .htacces
It's not a .htacces problem I can do the redirections as I want but when redirected to /public my vue file it's not being loaded, this is my app.js:
import Vue from 'vue';
import 'vuetify/dist/vuetify.min.css'
import Vuetify from 'vuetify'
import 'material-design-icons-iconfont/dist/material-design-icons.css'
import App from './App.vue';
import store from './store';
import router from './router';
Vue.use(Vuetify)
require('./bootstrap');
const opts = {}
import ApiService from './api/api.service';
ApiService.init();
window.Vue = require('vue');
const app = new Vue({
router,
store,
vuetify: new Vuetify(opts),
components: { App },
render: h => h(App)
}).$mount('#app');
this is my welcom.blade.php:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Administrador') }}</title>
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<!-- Fonts -->
<link rel="dns-prefetch" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css?family=Raleway:300,400,600" rel="stylesheet" type="text/css">
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app">
<index></index>
</div>
</body>
</html>
If you're not running php artisan serve what are you running? Laravel requires the server to be running PHP in order to serve the welcome.blade.php file.

DHTMLXGantt and Laravel - Data doesn't display in extended templates

Background
Following this tutorial from Jan 2016, ( https://dhtmlx.com/blog/using-dhtmlxgantt-with-laravel/ ) I began experimenting with DHTMLXGantt (v4.1) and Laravel (v5.4) and ran into some troubles getting the sample data from a mysql/mariadb database to display in the gantt chart. The initial troubles had to do with the DHTMLX connector not staying current with some Laravel changes. For the sake of others who may read this and are struggling with the same issues, the two basic problems I already solved were:
(1) I was referred to this [updated] connector which was compatible with Laravel's recent versions ( https://github.com/mperednya/connector-php/tree/modern ). And,
(2) I specified a date range that matched the dates of the sample data (from 2013), such as...
gantt.config.start_date = new Date(2013, 04, 01);
gantt.config.end_date = new Date(2013, 04, 30);
At this point I was able to successfully use Laravel as a backend server for the DHTMLXGantt chart (including read-write with the sample data).
Problem
The problem I am having now is trying to move from the simplistic sample, to something slightly more complex. Specifically, when I employ Laravel's extended templating I get the gantt chart painted on screen, but no project/task data displays in the chart.
To explain this a little more specifically, a simple Laravel view with the whole page contained within it works as expected. For example, this blade file (gantt.blade.php) works.
<!DOCTYPE html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script src="codebase/dhtmlxgantt.js"></script>
<link rel="stylesheet" href="codebase/dhtmlxgantt.css">
<link rel="stylesheet" href="codebase/skins/dhtmlxgantt_skyblue.css" type="text/css" media="screen" title="no title" charset="utf-8">
</head>
<body>
<div class="container">
<h1>Placeholder Header</h1>
<div id="gantt_here" style='width:100%; height:500px;'></div>
<script type="text/javascript">
gantt.config.xml_date = "%Y-%m-%d %H:%i:%s";
gantt.config.step = 1;
gantt.config.scale_unit= "week";
gantt.config.autosize = "xy";
gantt.config.fit_tasks = true;
gantt.config.columns = [
{name:"text", label:"Task name", width:"*", tree:true },
{name:"start_date", label:"Start time", align: "center" },
{name:"duration", label:"Duration", align: "center" },
{name:"add", label:"", width:44 }
];
gantt.init("gantt_here");
gantt.load("./gantt_data", "xml");
var dp = new gantt.dataProcessor("./gantt_data");
dp.init(gantt);
</script>
<h1>Placeholder Footer</h1>
</div>
</body>
But if I try using an extended app layout with the intention of building out a standard look & feel across all pages, the Gantt chart appears and is formated as I expect, but no data appears within the gantt chart. Here is top-level layout file (app.blade.php)
<!DOCTYPE html>
<html lang="{{ config('app.locale') }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<link rel="stylesheet" href="codebase/dhtmlxgantt.css">
<link rel="stylesheet" href="codebase/skins/dhtmlxgantt_skyblue.css" type="text/css" media="screen" title="no title" charset="utf-8">
<!-- Scripts -->
<script>
window.Laravel = {!! json_encode([
'csrfToken' => csrf_token(),
]) !!};
</script>
<script src="codebase/dhtmlxgantt.js"></script>
</head>
<body>
<div id="app">
<!-- menus and other bootstrap styling removed for brevity -->
#yield('content')
</div>
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
And here's the "content" view (index.blade.php)...
#extends('layouts.app')
#section('content')
<div id="gantt_here" style='width:100%; height:500px;'></div>
<script type="text/javascript">
gantt.config.xml_date = "%Y-%m-%d %H:%i:%s";
gantt.config.step = 1;
gantt.config.scale_unit= "week";
gantt.config.autosize = "xy";
gantt.config.fit_tasks = true;
gantt.config.columns = [
{name:"text", label:"Task name", width:"*", tree:true },
{name:"start_date", label:"Start time", align: "center" },
{name:"duration", label:"Duration", align: "center" },
{name:"add", label:"", width:44 }
];
gantt.init("gantt_here");
gantt.load("./gantt_data", "xml");
var dp = new gantt.dataProcessor("./gantt_data");
dp.init(gantt);
</script>
</div>
#endsection
Other things I've tried:
Using Chrome developer tools, I can see that the xml data was properly delivered to the browser in both examples. This made me think maybe it is a timing problem of some sort. So I put a couple links on the page just to test clearing the chart and reloading it. But still no change.
<a onclick="gantt.clearAll()" href="javascript:void(0);">Clear</a>
<a onclick="gantt.load('./gantt_data', 'xml')" href="javascript:void(0);">Refresh</a>
I also tried moving the div block "gantt_here" to various other places above and below Laravel's template directives. It fails in all cases, except when this div block is outside (either above or below) the "app" div tag in "app.blade.php" which, of course, defeats the purpose I am trying to achieve.
My goal is to use this chart within Laravel's extended templating capabilities. But I can't figure out what's wrong. Any ideas?
After further troubleshooting, I discovered the problem. It turns out that in app.blade.php, I was loading the app.js at the bottom of the body tag. When I moved this up to the HTML header area, the data began to display properly.

Resources