Laravel VueJS error when new instance inside blade [duplicate] - laravel

In Laravel projects prior to 5.3 I've utilised Vue.js using the script tag like this:
<script type="text/javascript" src="../js/vue.js"></script>
I would then create a Vue instance specific for that page like this:
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
});
</script>
and then bind it to the relevant div#id in my HTML.
Now, in Laravel 5.3 Vue.js comes bundled and I am fully aware that I can use components as described in the docs by using gulp/elixir, however, my question is if I want to create a Vue.js instance like I just mentioned, i.e. where I create a Vue.js instance strictly for a given page (not a component) how do I do it?
Do I set it up like I used to by importing the vue.js library in a script tag or can I use generated app.js?
Am I not supposed to do it this way, should I be creating components for everything?
For me, it doesn't make sense to make a component for something I am only using once - I thought the purpose of components was that they are reusable - you can use it in more than one place. As mentioned in the Vue.js docs:
Components are one of the most powerful features of Vue.js. They help you extend basic HTML elements to encapsulate reusable code.
Any advice would be appreciated, thanks!

I'd leave Laravel the way it comes, with Webpack. This gives you the ability to add some good Webpack configuration. Plus gulp watch works inside the Homestead vagrant VM now since it will be using Webpack to watch the file changes. And also check out async components.
Now on to your question regarding separate Vue instances per page...let's start with app.js...
App.js
When you first install Laravel 5.3, you'll find an app.js entry point. Let's comment out the main Vue instance:
resources/assets/js/app.js
/**
* First we will load all of this project's JavaScript dependencies which
* include Vue and Vue Resource. This gives a great starting point for
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
/**
* 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', require('./components/Example.vue'));
// Let's comment this out, each page will be its own main Vue instance.
//
// const app = new Vue({
// el: '#app'
// });
The app.js file still remains a place to for global stuff, so components added here are available (such as the example component seen above) to any page script that includes it.
Welcome Page Script
Now let's create a script that represents a Welcome Page:
resources/assets/js/pages/welcome.js
require('../app')
import Greeting from '../components/Greeting.vue'
var app = new Vue({
name: 'App',
el: '#app',
components: { Greeting },
data: {
test: 'This is from the welcome page component'
}
})
Blog Page Script
Now let's create another script that represents a Blog Page:
resources/assets/js/pages/blog.js
require('../app')
import Greeting from '../components/Greeting.vue'
var app = new Vue({
name: 'App',
el: '#app',
components: { Greeting },
data: {
test: 'This is from the blog page component'
}
})
Greeting Component
resources/assets/js/components/Greeting.vue
<template>
<div class="greeting">
{{ message }}
</div>
</template>
<script>
export default {
name: 'Greeting',
data: () => {
return {
message: 'This is greeting component'
}
}
}
</script>
Welcome Blade View
Let's update the welcome blade view that ships with Laravel:
<!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>Laravel</title>
</head>
<body>
<div id="app">
<example></example>
#{{ pageMessage }}
<greeting></greeting>
</div>
<script src="/js/welcome.js"></script>
</body>
</html>
The idea would be the same for the blog view.
Elixir
Now bring it all together in your gulp file using Elixir's ability to merge Webpack config options with its own (read more about that here):
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 => {
var config = elixir.webpack.mergeConfig({
entry: {
welcome: './resources/assets/js/pages/welcome.js',
blog: './resources/assets/js/pages/blog.js'
},
output: {
filename: '[name].js' // Template based on keys in entry above
}
});
mix.sass('app.scss')
.webpack('app.js', null, null, null, config);
});
Run gulp or gulp watch and you'll see both welcome.js and blog.js published.
Thoughts
I'm currently going the SPA route when it comes to "web apps" and just using Laravel as the backend API (or any other language/framework). I've seen some examples where Vue SPA is built in Laravel, but I really think it should be a completely seperate repo/project, independent of the backend. There's no Laravel/PHP templating views involved in an SPA, so build out the SPA separately. BTW, the SPA would have "page" components (which are usually called by VueRouter and of course would be made up of more nested components...see my example project link below).
However, for the "web site" I think Laravel is still a good choice for serving blade views and no need to go SPA for that. You can do what I've described in this answer. Also, you can connect your website to your webapp. On your website, you would have a "login" link that will take a user from the website to the webapp SPA to login. Your website remains SEO friendly (although there is good proof that Google is seeing content on SPA javascript sites as well).
For a look at an SPA approach, I've put up an example in Vue 2.0 here: https://github.com/prograhammer/example-vue-project (it works great, but still in progress).
Edit:
You may want to also checkout the Commons Chunk Plugin. This way browsers can cache some shared module dependencies separately. Webpack automatically can pull out shared imported dependencies and put them in a separate file. So that you have a both a common.js(shared stuff) and a welcome.js on a page. Then on another page you would again have common.js and blog.js and the browser can reuse the cached common.js.

If you want to incorporate vuejs into app.js using gulp then you can do it with elixir:
Firstly, you need laravel-elixir-browserify-official from npm:
npm install laravel-elixir-browserify-official
Then place the following in package.json:
"browserify": {
"transform": [
"vueify",
"babelify"
]
}
Your resources/assets/js/app.js file would then just need:
require('./bootstrap');
The bootstrap.js file should be in the "resources/assets/js" folder. I can't remember if this got installed with passport in my application, so if you don't have it then laravel provided the following code for "bootstrap.js":
window._ = require('lodash');
/**
* We'll load jQuery and the Bootstrap jQuery plugin which provides support
* for JavaScript based Bootstrap features such as modals and tabs. This
* code may be modified to fit the specific needs of your application.
*/
window.$ = window.jQuery = require('jquery');
require('bootstrap-sass');
/**
* Vue is a modern JavaScript library for building interactive web interfaces
* using reactive data binding and reusable components. Vue's API is clean
* and simple, leaving you to focus on building your next great project.
*/
window.Vue = require('vue');
require('vue-resource');
/**
* We'll register a HTTP interceptor to attach the "CSRF" header to each of
* the outgoing requests issued by this application. The CSRF middleware
* included with Laravel will automatically verify the header's value.
*/
Vue.http.interceptors.push((request, next) => {
request.headers['X-CSRF-TOKEN'] = Laravel.csrfToken;
next();
});
/**
* Echo exposes an expressive API for subscribing to channels and listening
* for events that are broadcast by Laravel. Echo and event broadcasting
* allows your team to easily build robust real-time web applications.
*/
// import Echo from "laravel-echo"
// window.Echo = new Echo({
// broadcaster: 'pusher',
// key: 'your-pusher-key'
// });
Now in gulpfile.js you can use:
elixir(function(mix) {
mix.browserify('app.js');
});
And in your HTML you would have:
...
<div id="app">
#{{message}}
</div>
...
<script type="text/javascript">
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
});
</script>
Now just run gulp
If you are not using elixir then you should be able to do a similar thing with the browserify or webpack packages from npm.
Edit
To answer your updated question, you can of course use vue.js for a single page. I personally use knockout for this stuff (I'm using vue because laravel passport uses it), but architecturally they are the same - they are MVVM libraries.
The point in MVVM is to bind your view to an underlying data model, so when one updates the other is automatically updated (i.e. updates in the dom automatically update the model and vice verser). Vue components are a simple way to reuse blocks of code, which is really good for creating widgets or complex components, but if you are simply looking to render data from a view model on to your page, then you would not usually need to create a component for that.
As for generating app.js, this entirely depends on your project. You cannot bind more than one view model to a view, so if you plan on using multiple view models in your project you would need to find a way to include the specific view model for your page. To achieve that I would probably remove the view model from app.js and keep the bootstrap and registered components there, then create separate view models that would need to be included on each page.

If you are on Laravel 5.5 and beyond, here is the best solution if you want to utilize the power of Blade but still enjoy reactive of VueJS
https://stackoverflow.com/a/54349029/417899

Related

Inertiajs - Switch to another page locally

I would like to know how to switch between different pages on the client side only, without inertia.visit().
I am using Laravel and Inertiajs.
I understand that props must be specified from the laravel side in order to move to another page.
Is there any way to switch pages without communication between client and server?
I want to switch pages only on the client side with the URL, not by switching components within the same page.
Not sure if you are asking for this, but InertiaJS has an alternative for manual visits - the InertiaJS Link:
<template>
<Link href="/myPage" v-text="`Click me`" />
</template>
<script setup>
import { Link } from '#inertiajs/inertia-vue3'
</script>
Logically, anyways you'll have to register a route in routes/web.php, else you'll get a 404:
Route::get('/myPage', function () {
return inertia('MyPage');
});

How to integrate individually working Laravel and Vue code that does not work well together

I am trying to integrate a Laravel application I wrote and a Vue application my friend wrote together. While both work perfectly on their own, together I am getting a ton of errors. It appears that Vue and/or Laravel simply isn't seeing certain elements, and I'm not sure why.
One of the tags in my home.php:
<div class="start" id="inputData">
<h1><span v-bind:title="welcomeDate">#{{welcomeMessage}}</span></h1>
</div>
The relevant code in vue.js, which is inside a onload() method. If I don't have onload, it throws other errors, which I can give if relevant.
var welcome = new Vue({
el: '#inputData',
data: {
welcomeMessage: 'Welcome, user.',
welcomeDate: "You loaded this page on " + new Date().toLocaleString()
}
});
Vue is imported in the blade for the main page, via:
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.10/dist/vue.js"</script>
<script src="{{ asset('js/vue.js') }}"></script>
The error it throws (in chrome console):
ReferenceError: inputData is not defined
I realize these are code snippets but it is a fairly big application and I don't want to give an overwhelming amount of code. Any help is greatly appreciated.

Why is Vue.js not showing anything in Laravel 5.6?

I have installed vue.js by following these steps in Laravel 5.6 and all other dependencies are working perfectly. Only Vue.js is not responding.
npm intall
npm run dev
npm run watch
I am sharing all the codes on I have added. I have created a id="app" in my html file.
<div id="app">
<div class="container">
<articles></articles>
</div>
<!-- I used this link in my html file for connecting with app.js file
-->
<script src="{{asset('js/app.js')}}"></script>
I edited the app.js file that is as under.
require('./bootstrap');
window.Vue = require('vue');
Vue.component('articles', require('./components/Articles.vue')
);
const app = new Vue({
el: '#app'
});
I also created Articles.vue file and linked that to app.js. But my html page is showing nothing.
My file in components/Articles.Vue
<template>
<h1>Hello World!</h1>
</template>
Console is showing no errors
Vue Tab
When I inspect DOM, I get this
This is the Vue file. It is also not showing any tags
As ceejayoz said in the comment: Rename it to e.g. articleElement and use it as <article-element></article-element>
this thread is a bit old, but as i had the same problem as you had (maybe we both watched the same youtube video "Full Stack Vue.js & Laravel"), i will still share my solution. With some research and a lot of trying around i landed on the official Laravel page (https://laravel-mix.com/docs/6.0/what-is-mix).
The last task of this guide "npx mix" did the job for me. Everytime i change some of my js files now i use this little command to compile again and all my changes take place.
Hopefully this will help some others too :)

Laravel 5.7 and ExtJS 5 app configuration

I am trying for the first time to create an application with Laravel 5.7 and ExtJS 5.
There is a lot of information for Laravel / Vue and Laravel / Angular applications, but for Laravel / ExtJS it is practically non-existent (unfortunately).
I created an ExtJS app called extjs_app with cmd that I put in the public folder of the Laravel project.
In the Laravel views folder I created a view named index_extjs.blade.php containing the index.html code of the ExtJS app with the following change:
<script id="microloader" type="text/javascript" src="bootstrap.js"></script>
replaced for
<script id="microloader" type="text/javascript" src="extjs_app/bootstrap.js"></script>
And in the bootstrap.js file (I probably should not edit this file):
Ext.manifest = Ext.manifest || "bootstrap.json";
replaced for
Ext.manifest = Ext.manifest || "extjs_app / bootstrap.json"
And in the app.json file
indexHtmlPath": "index.html"
replaced for
"indexHtmlPath": "../../../resources/views/index_extjs.php"
However, despite several attempts, the files required for the ExtJS application are not loaded.
How to properly configure Laravel and ExtJS to work together?
You need to set the root route for the entire application to be served with your blade view, in your case index_extjs.blade.php.
Why? Because when anyone opens up your site, you are loading up that page and hence, loading extjs too. After that page is loaded, you can handle page changes through extjs.
So to achieve this, you need to declare your root route to server this index file:
Route::get('/', function() {
return view('index_extjs');
});
Also you need to revert all extjs config changes back to default, because everything will be relative to your extjs app inside public folder and not relative to the project itself. I hope this makes sense

Vue Component not showing - Passport Implemenation Laravel 5.4

I am trying implement passport using Laravel 5.4 and I have followed the official documentation step by step. Everything seems to be working fine as per instructions till the point I hit "Frontend Quickstart"
As instructed I published the vendor using
php artisan vendor:publish --tag=passport-components
This gave me the components as expected. After which I registered my components in my app.js
app.js
/**
* Add the CSRF Token to the Laravel object. The Laravel object is being
* used by Axios and the reference can be seen in ./bootstrap.js
*
* Requires the token be set as a meta tag as described in the documentation:
* https://laravel.com/docs/5.4/csrf#csrf-x-csrf-token
*/
window.Laravel = { csrfToken: document.head.querySelector("[name=csrf-token]").content }
/**
* 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');
/**
* The Vue components for managing the OAuth setup
*/
Vue.component(
'passport-clients',
require('./components/passport/Clients.vue')
);
Vue.component(
'passport-authorized-clients',
require('./components/passport/AuthorizedClients.vue')
);
Vue.component(
'passport-personal-access-tokens',
require('./components/passport/PersonalAccessTokens.vue')
);
/**
* Instantiate Vue for use
*/
const app = new Vue({
el: '#app'
});
I installed the dependencies and build the components
npm install
npm run dev
Placed the components in my home.blade.php (test purpose)
#extends('layouts.app')
#section('content')
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">Dashboard</div>
<div class="panel-body">
<passport-clients></passport-clients>
<passport-authorized-clients></passport-authorized-clients>
<passport-personal-access-tokens></passport-personal-access-tokens>
</div>
</div>
</div>
</div>
</div>
#endsection
But nothing shows up in the view. I tried searching a lot in this topic but all the solutions seems to be pointing towards the gulp config. But Laravel 5.4 doesn't use gulp anymore it uses webmix.
I have been struggling with this for a while now, looking for the communities expert option to help be get through this.
Thanking You.
Make sure you've added <script src="{{ asset('js/vue.min.js')}}"></script> on your layouts.app file.
From official document
In order to use the Passport Vue components, you must be using the Vue
JavaScript framework. These components also use the Bootstrap CSS
framework. However, even if you are not using these tools, the
components serve as a valuable reference for your own frontend
implementation.
Download vuejs here
Hope this help
In your dom, your components must have a parent with an id of "app" since you declared it in your app.js :
const app = new Vue({
el: '#app'
});

Resources