I try to integrate vue.js with laravel 5.3. I call "gulp" which creates the main.js file in the public folder. I can see in the browser that the js file is loaded but the value of "message" is not shown. It is only written {{message}}. Any ideas why?
<body>
<div class="container">
<div class="content">
<div class="title">
<p>#{{ message }}</p>
</div>
</div>
</div>
<script src="js/main.js"></script>
</body>
gulpfile:
var elixir = require('laravel-elixir');
require('laravel-elixir-browserify-official');
require('laravel-elixir-vueify');
elixir(mix => {
mix.sass('app.scss').browserify('main.js');
});
main.js:
import Vue from 'vue';
var app = new Vue({
el: 'body',
data: {
message: 'Hello Vue!'
}
})
package.json:
"dependencies": {
"bootstrap-sass": "^3.3.7",
"gulp": "^3.9.1",
"jquery": "^3.1.0",
"laravel-elixir": "^6.0.0-9",
"laravel-elixir-browserify-official": "^0.1.3",
"laravel-elixir-vue-2": "^0.2.0",
"laravel-elixir-vueify": "^1.0.0",
"laravel-elixir-webpack-official": "^1.0.2",
"lodash": "^4.16.2",
"vue": "^2.0.1",
"vue-resource": "^1.0.3"
}
EDIT
package.json
{
"private": true,
"scripts": {
"prod": "gulp --production",
"dev": "gulp watch",
"slate": "rimraf node_modules && npm install",
"clean": "rimraf public/css/app.css public/css/app.css.map public/js/app.js && npm run dev"
},
"devDependencies": {
"bootstrap-sass": "^3.3.7",
"gulp": "^3.9.1",
"jquery": "^3.1.1",
"laravel-elixir": "^6.0.0-15",
"laravel-elixir-browsersync-official": "^1.0.0",
"laravel-elixir-vue-2": "^0.3.0",
"laravel-elixir-webpack-official": "^1.0.10",
"lodash": "^4.17.2",
"moment": "^2.17.1",
"vue": "^2.1.6",
"vue-resource": "^1.0.3",
"vuex": "^2.1.1"
}
}
gulpfile.js
const elixir = require('laravel-elixir');
require('laravel-elixir-vue-2');
/*
|--------------------------------------------------------------------------
| Elixir Asset Management
|--------------------------------------------------------------------------
|
| Elixir provides a clean, fluent API for defining some basic Gulp tasks
| for your Laravel application. By default, we are compiling the Sass
| file for our application, as well as publishing vendor resources.
|
*/
elixir(mix => {
mix
.sass('app.scss')
.webpack('main.js');
});
Your code is fine except one thing. Vue JS Doesn't recommend use of body element as vue js root.
The provided element merely serves as a mounting point. Unlike in Vue
1.x, the mounted element will be replaced with Vue-generated DOM in all cases. It is therefore not recommended to mount the root instance to or
https://v2.vuejs.org/v2/api/#el
Code
<body>
<div class="container" id="app"> <!-- Mind the id attached -->
<div class="content">
<div class="title">
<p>#{{ message }}</p>
</div>
</div>
</div>
<script src="js/main.js"></script>
</body>
and main.js
import Vue from 'vue';
var app = new Vue({
el: '#app', // mind the root element is changed to app.
data: {
return { // mind the return in data
message: 'Hello Vue!'
}
}
});
Related
I am using Laravel Jetstream and InertiaJS. I tried to make a pagination according to the manual.
web.php
use App\Models\Post;
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
Route::get('/posts', function () {
return Inertia::render('Posts', [
'posts' => Post::paginate(2)->through(fn($post) => [
'id' => $post->id,
'title' => $post->title,
'body' => $post->body
])
]);
})->name('pages.posts');
Posts.vue
<script setup>
import { Link } from '#inertiajs/inertia-vue3';
import NewLayout from '#/Layouts/NewLayout.vue';
defineProps({posts: Object});
</script>
<template>
<NewLayout title="posts">
<div>
<div class="m-10 border w-400" v-for="post in posts.data" :key="post.id">
<div>{{ post.title }}</div>
<div>{{ post.body }}</div>
</div>
</div>
<div class="inline-flex -space-x-px">
<a class="bg-white border border-gray-300 text-gray-500 hover:bg-gray-100 hover:text-gray-700 ml-0 rounded-l-lg leading-tight py-2 px-3 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"
v-for="link in posts.links" :href="link.url" v-html="link.label"></a>
</div>
</NewLayout>
</template>
'posts' => Post::paginate(4)
when I change the pagination value to 4 in the web.php file, it shows 4 posts
'posts' => Post::paginate(2)
and when I enter the value 2, it displays the first two posts (and so far everything works as it should)
but when i click on the second page nothing changes. the same first two posts are displayed
I don't know what I did wrong. please, help.
I use laravel 9, docker, nginx, mysql
package.json
{
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"#inertiajs/inertia": "^0.11.0",
"#inertiajs/inertia-vue3": "^0.6.0",
"#inertiajs/progress": "^0.2.7",
"#tailwindcss/forms": "^0.5.2",
"#tailwindcss/typography": "^0.5.2",
"#vitejs/plugin-vue": "^4.0.0",
"autoprefixer": "^10.4.7",
"axios": "^1.1.2",
"laravel-vite-plugin": "^0.7.2",
"lodash": "^4.17.19",
"postcss": "^8.4.14",
"tailwindcss": "^3.1.0",
"vite": "^4.0.0",
"vue": "^3.2.31"
}
}
Laravel paginator takes GET parameter page from the request object. You don't provide that object to function that's why it doesn't work. Try this
Route::get('/posts', function (Request $request) {...})->name('pages.posts');
Or you may specify the page manually:
Route::get('/posts', function (Request $request) {
return Inertia::render('Posts', [
'posts' => Post::paginate(2, page: $request->page ?? 1)->through(fn($post) => [
'id' => $post->id,
'title' => $post->title,
'body' => $post->body
])
]);
})->name('pages.posts');
I specified in the nginx.conf file like this
location / {
try_files $uri /index.php;
}
and it was necessary like this
location / {
try_files $uri /index.php?$query_string;
}
I have just created a new laravel project, using sail / docker. Installed tailwind, laravel-livewire, alpine. my package.json looks like this:
{
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"autoprefixer": "^10.4.13",
"axios": "^1.1.2",
"laravel-vite-plugin": "^0.6.0",
"lodash": "^4.17.19",
"postcss": "^8.4.18",
"tailwindcss": "^3.2.2",
"vite": "^3.0.0"
},
"dependencies": {
"#alpinejs/focus": "^3.10.5",
"#defstudio/vite-livewire-plugin": "^0.2.6",
"#tailwindcss/forms": "^0.5.3",
"alpinejs": "^3.10.5"
}
}
I have a livewire component, a form, that you choose your Property that you live in, then choose the unit on that property. People are making maintenance requests for their apartment to their apartment manager.
So when the user / tenant identifies their property, function updated($property) does the validation only for the field that changed, then if passes, runs a query to find the list of apartments available for that property. I dd() at the end of the function and I know it is returning the proper list of apartments and their id's for the property chosen in the form.
However, as soon as livewire tries to send the data back to the form, I get a totally blank screen. In fact, I don't think the data is making it out of the back end because in the console, I do not see the apartment unit request being returned, but again, on the back end, if I dd($units), they are all their.
I think it is a Vite / livewire issue going on. I cannot identify it.
Here is the code in the livewire component. I include the dd(), and it does return the appropriate values to the screen, so the app is getting to the end of the updated() function:
public function updated($propertyname)
{
$this->validateOnly($propertyname, $this->rules(), $this->customMessages());
switch ($propertyname) {
case 'submittedby':
$this->submittedby = ucWordsSpace($this->submittedby);
break;
case 'phonenumber':
if (strlen($this->phonenumber) > 0)
$this->phonenumber = formatphone($this->phonenumber, false);
break;
case 'property':
$this->unit_options = array();
$this->unit_values = array();
$this->unit_values[0] = -1;
$units = Unit::where('property_id',4)->select('id','abbrev')->orderBy('abbrev')->get();
$this->unit_options[0] = (count($units) == 0) ? 'Choose Your Property First' : 'Choose Your Unit';
foreach ($units as $unit) {
$this->unit_values[] = $unit->id;
$this->unit_options[] = $unit->abbrev;
}
dd($this->unit_values, $this->unit_options);
break;
}
}
I have the following in layout.app.blade.php in the :
#vite('resources/css/app.css', 'resources/js/app.js')
the following is in my tailwind.config.js
module.exports = {
content: [
"./resources/**/*.blade.php",
"./resources/**/*.js",
"./resources/**/*.vue",
],
resources/css/app.css contains:
#tailwind base;
#tailwind components;
#tailwind utilities;
resources/js/app.js contains:
import './bootstrap';
import '../css/app.css';
bootstrap.js contains:
window._ = _;
/**
* We'll load the axios HTTP library which allows us to easily issue requests
* to our Laravel back-end. This library automatically handles sending the
* CSRF token as a header based on the value of the "XSRF" token cookie.
*/
import axios from 'axios';
window.axios = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
import Alpine from 'alpinejs'
import focus from '#alpinejs/focus'
window.Alpine = Alpine
Alpine.plugin(focus)
Alpine.start()
vite.config.js contains:
import {defineConfig} from 'vite';
import laravel from 'laravel-vite-plugin';
import livewire from '#defstudio/vite-livewire-plugin'; // <-- import
export default defineConfig({
//...
plugins: [
laravel([
'resources/css/app.css',
'resources/js/app.js',
]),
livewire({ // <-- add livewire plugin
refresh: ['resources/css/app.css'], // <-- will refresh css (tailwind ) as well
}),
],
});
Signed Dazed and Confused!
Hope someone has some insite.
okay, i have something to add. here is a component that I am using
#props([
'label' => '',
'model' => '',
'pholder' => '',
'speed' => '',
])
<div>
<div class="rounded-md border border-gray-300 px-3 py-2 mb-3 shadow-sm focus-within:border-indigo-600 focus-within:ring-1 focus-within:ring-indigo-600">
<label for="{{$model}}" class="block text-xs font-medium text-gray-900">{{$label}}</label>
<input type="text"
wire:model{{$speed}}="{{$model}}"
id="{{$model}}"
class="block w-full border-0 p-0 text-gray-900 placeholder-gray-400 focus:ring-0 sm:text-sm"
placeholder="{{$pholder}}">
</div>
#error($model)<span class="text-red-800 text-xs underline">{{ $message }}</span> #enderror
</div>
the livewire component 'calls' this component thus:
<x-hab-input label="Phone Number"
model="phonenumber"
pholder="(999) 999-9999"
speed=".lazy" />
I have this rule defined in the livewire component:
'phonenumber' => ['regex:/^([0-9\s\-\+\(\)]*)$/', 'min:10', 'max:14', 'required'],
i have the following code running after the field is updated
public function updated($propertyname)
{
$this->validateOnly($propertyname, $this->rules(), $this->customMessages());
switch ($propertyname) {
case 'submittedby':
$this->submittedby = ucWordsSpace($this->submittedby);
break;
case 'phonenumber':
if (strlen($this->phonenumber) > 0)
$this->phonenumber = formatphone($this->phonenumber, false);
break;
the formatphone() function is a helper function that resides in App/helpers.php. the function turns a phone number typed like "4045551212" into "(404) 555-1212". This function works. It updates the formatting of the phone number.
However, if user types, e.g., less than 10 numbers it will fail the validation, which is supposed to flash the error to the screen. But, this is another situation where the screen goes blank. gone. only the background is there. The {{$slot}} in app.blade.php is left empty.
well, I am both angry at myself and embarassed. Here is the culprit. There was a comment at the top of the livewire component. Damn. I took it out, and no problems!
<!--
This example requires some changes to your config:
// tailwind.config.js
module.exports = {
// ...
plugins: [
// ...
require('#tailwindcss/forms'),
],
}
-->
<div>
<div class="w-3/4 mt-5 mx-auto rounded-2xl p-5 bg-slate-100">
<p class="text-3xl font-serif text-red-900 text-center">Habersham Properties - Maintenance Request</p>
<div class="hidden sm:block" aria-hidden="true">
Well i am playing with the new laravel 5.3 and vue.js and i want to do a GET call to some users i have in my DB
Im using components btw.
This is my app.js
require('./bootstrap');
Vue.component('example', require('./components/UserComponents/User.vue'));
const app = new Vue({
el: 'body',
});
This is my component User.vue i left the HTML template out for post size reason i can post it if neccesary
<script>
export default{
data : function () {
return {
users : ''
}
},
methods: {
fetchUser: function () {
var vm = this;
vm.$http.get('user/', function (data) {
vm.$set('users', data)
})
}
},
ready() {
this.fetchUser();
},
}
</script>
Im getting 2 errors in the console
vue-resource.common.js?d39b:27 0ReferenceError: Laravel is not defined(…)
(program):29 Uncaught (in promise) ReferenceError: Laravel is not defined(…)
this is my package.json as you can see i have all the deps for this to work vue and vue resource
{
"private": true,
"scripts": {
"prod": "gulp --production",
"dev": "gulp watch"
},
"devDependencies": {
"bootstrap-sass": "^3.3.7",
"gulp": "^3.9.1",
"jquery": "^3.1.0",
"laravel-elixir": "^6.0.0-9",
"laravel-elixir-vue": "^0.1.4",
"laravel-elixir-webpack-official": "^1.0.2",
"lodash": "^4.14.0",
"vue": "^1.0.26",
"vue-resource": "^0.9.3"
}
}
Hope someone could help me out here. Thank you
Or for a cleaner format:
<script>
window.Laravel = { csrfToken: '{{ csrf_token() }}' };
</script>
Does same thing as Rocco's answer.
Try to put this on your blade, as you can see is inserted by default on app.blade on Laravel 5.3
<script>
window.Laravel = <?php echo json_encode([
'csrfToken' => csrf_token(),
]); ?>
</script>
if you're using axios then ensure the following is in your bootstrap.js file after axios is imported:
window.axios.defaults.headers.common = {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
'X-Requested-With': 'XMLHttpRequest'
};
I'm trying to use Font Awesome with Vue + laravel project.
I have it in my package.json
"devDependencies": {
"#fortawesome/fontawesome-free": "^5.15.4",
"axios": "^0.21.4",
"bootstrap": "^4.6.0",
"jquery": "^3.6",
"laravel-mix": "^6.0.34",
"lodash": "^4.17.19",
"popper.js": "^1.16.1",
"postcss": "^8.3.11",
"resolve-url-loader": "^3.1.4",
"sass": "^1.43.3",
"sass-loader": "^11.0.1",
"vue": "^2.6.14",
"vue-loader": "^15.9.8",
"vue-template-compiler": "^2.6.14"
},
Imported FontAwesome in main.js
import { library } from '#fortawesome/fontawesome-svg-core'
import { faSpinner } from '#fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '#fortawesome/vue-fontawesome'
I am Use:
<i class="fas fa-ellipsis-v"></i>
But Not Show Icon !!
Read document
https://github.com/FortAwesome/vue-fontawesome
You need add to main.js
Vue.component('font-awesome-icon', FontAwesomeIcon)
and use tag <font-awesome-icon icon="***" />
Example:
<font-awesome-icon icon="ellipsis-v" />
When i load my page, calendar not working and on my console i have :
jQuery.Deferred exception: FullCalendar is not defined ReferenceError: FullCalendar is not defined
at HTMLDocument.<anonymous> (http://admin.test/agenda:279:20)
at mightThrow (http://admin.test/js/admin.js:30047:29)
at process (http://admin.test/js/admin.js:30115:12) undefined
admin.js:30340 Uncaught ReferenceError: FullCalendar is not defined
at HTMLDocument.<anonymous> (agenda:279)
at mightThrow (admin.js:30047)
at process (admin.js:30115)
1) I have a laravel project with "AdminLTE 3.0.5".
Package.json :
"devDependencies": {
"#fullcalendar/bootstrap": "^4.4.0",
"#fullcalendar/core": "^4.4.0",
"#fullcalendar/daygrid": "^4.4.0",
"#fullcalendar/interaction": "^4.4.0",
"#fullcalendar/timegrid": "^4.4.0",
"admin-lte": "^3.0.5",
"axios": "^0.19",
"bootstrap": "^4.4.1",
"jquery": "^3.4.1",
"jquery-ui": "^1.12.1",
"laravel-mix": "^5.0.1",
"lodash": "^4.17.13",
"popper.js": "^1.12",
"resolve-url-loader": "^2.3.1",
"sass": "^1.20.1",
"sass-loader": "^8.0.0",
"vue": "^2.5.17",
"vue-template-compiler": "^2.6.10"
},
2) I import Fullcalendar package with my webpack :
mix.js('resources/js/app.js', 'public/js/app.js')
.js('resources/js/calendar.js', 'public/js/calendar.js')
app.js :
require('./bootstrap');
window.Vue = require('vue');
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
const app = new Vue({
el: '#app',
});
require('jquery-ui/ui/widgets/draggable');
require('admin-lte');
/* Table */
require('../../node_modules/admin-lte/plugins/datatables/jquery.dataTables.min.js');
require('../../node_modules/admin-lte/plugins/datatables-bs4/js/dataTables.bootstrap4.min.js');
require('../../node_modules/admin-lte/plugins/datatables-responsive/js/dataTables.responsive.min.js');
require('../../node_modules/admin-lte/plugins/datatables-responsive/js/responsive.bootstrap4.min.js');
require('../../node_modules/admin-lte/plugins/bs-custom-file-input/bs-custom-file-input.min.js');
calendar.js :
/* Calendar */
require('#fullcalendar/core');
require('#fullcalendar/daygrid');
require('#fullcalendar/timegrid');
require('#fullcalendar/interaction');
require('#fullcalendar/bootstrap');
3) On my vue, i copy/past the AdminLTE3 calendar page and only add my 2 mix file before :
<script src="{{ mix('js/app.js') }}"></script>
<script src="{{ mix('js/calendar.js') }}"></script>
<script>
$(function () {
/* initialize the external events
-----------------------------------------------------------------*/
function ini_events(ele) {
ele.each(function () {
[...]
I use "require()" function to call all js files, and when i run "npm run dev", everything work, no error.
I think that it's a js file order, but it's the same order than AdminLTE3 calendar page... or i'm blind.
I changed all versions of the calendar package & jquery & jquery-ui to have the same that this page (4.4.0 for my dl version).
Someone can help me pls ?
I have the solution.
Imports files like that on my calendar.js :
/* Calendar */
import { Calendar } from '#fullcalendar/core';
import dayGrid from '#fullcalendar/daygrid';
import timeGrid from '#fullcalendar/timegrid';
import interaction, { Draggable } from '#fullcalendar/interaction';
import bootstrap from '#fullcalendar/bootstrap';
And you dont need this 2 lines on my script
<!--
var Calendar = FullCalendar.Calendar;
var Draggable = FullCalendarInteraction.Draggable;
-->