Laravel - Vue Multiple Page Application with Single Vue Instance - laravel

I am using Laravel for a project and would like to switch Vue. This is a sample of my setup right now:-
"routes/web.php"
Route::get('/home', 'HomeController#home');
Route::get('/about', 'HomeController#about');
Route::get('/blogs', 'HomeController#blogs');
"views/master.blade.php"
<!DOCTYPE html>
<html>
<head>
<title>#yield('title')</title>
<!-- AND OTHER STUFF -->
</head>
<body>
<!-- NAV BAR -->
<div id="app">
#yield('content')
</div>
<script src="app.build.js"></script>
</body>
</html>
"views/pages/home.blade.php"
#extends('master')
#section('title', "Home")
#section('content')
<home-content
customproperties="{{ $somedata }}"
></home-content>
#endsection
"app.js"
var vm = new Vue({
data(){
return {
}
},
components: {
HomeContent,
AboutContent,
BlogsContent
}
})
Let's suppose I have all the components ready and working just fine. The problem is, am I doing it the right way? I don't want to make it a single page application for project complexity, instead I want to do it hybrid way. All vue components will have their respective pages, and some pages will not even have a vue component, just a Plain Blade page.
For example, a static page may look like this:-
#extends('master')
#section('title', "Static Page")
#section('content')
Just a static page, it has nothing to do with vue, but still sitting inside Vue instance's template scope.
#endsection
For these pages, the vue script is being loaded and "#app" is getting interpreted as a template. But this page will have no use for vue. Is it good to leave it this way? Or a more optimal way exists for this?
Any suggestions regarding best practices for Laravel-Vue multi page application is welcome.

Related

Laravel 5.7 cant use assets with Vue in blade template

Hello I have Laravel version 5.7.24. I have problem with import app.js to blade template.
I have app.js in resources/js/app.js, this same file is other location: public/js/app.js
In welcome.blade.php I add:
<body>
<div id="app">
Hello
<example-component></example-component>
<articles></articles>
</div>
<script src="{{ asset('js/app.js') }}"></script>
</body>
I created articles component in resources/js/components/articles.vue:
<template>
<div>
Hello
</div>
</template>
<script>
export default {
name: "Articles"
}
</script>
Now Laravel return me error:
Unknown custom element: - did you register the component
correctly? For recursive components, make sure to provide the "name"
option.
Because asset refers to the public/js/app.js
I read in this article, taht Laravel removed assets foler. So I added assets folder and my file structure looks like this:
but still Laravel references the file public/js/app.js.
How I can import srcipt (resources/js/app.js) to my welcome.blade.php file ?
Edit:
my resources/js/app.js file:
require('./bootstrap');
window.Vue = require('vue');
Vue.component('articles', require('./components/Articles.vue').default);
const app = new Vue({
el: '#app'
});
When I change script from (in welcome.blade.php):
<script src="{{ asset('js/app.js') }}"></script>
to
<script src="{{ asset('assets/js/app.js') }}"></script>
I have error: GET http://127.0.0.1:8000/assets/js/app.js
net::ERR_ABORTED 404 (Not Found)
It looks like you have a mistake in this line of your app.js:
Vue.component('articles', require('./components/Articles.vue').default);
Try removing .default from here, and see if the component is registered correctly when you build again (npm run dev).
Side note: <articles> should contain a hyphen like my-articles, v-articles, or something else.
When using a component directly in the DOM (as opposed to in a string
template or single-file component), we strongly recommend following
the W3C rules for custom tag names (all-lowercase, must contain a
hyphen). This helps you avoid conflicts with current and future HTML
elements.
https://v2.vuejs.org/v2/guide/components-registration.html#Component-Names

Laravel Blade #yield is not working inside included view

I am trying to make layout using blade but the problem is that when i tried to
#yield on the file which is included in master file but #yield is not working.
resouces/views/layouts/app.blade.php
<html>
<head>
...
...
</head>
<body>
#include('layouts.navigation')
#include('layouts.main_panel')
#include('layouts.footer')
</body>
</html>
resouces/views/layouts/main_panel.blade.php
// some html stuff
#yield('form')
// some html stuff
resouces/views/auth/login.blade.php
#extends('layouts.app')
#section('form')
<form>
// input
</form>
#endsection
I would suggest you pass variables to the partials and echo
them inside it. This is an alternative way to achieve what you are
trying to do.
For example -
Partial blade file (resouces/views/partials.header.blade.php) -
<h4>{{ $name }}</h4>
View (resouces/views/custom.blade.php) -
#include('partials.header', [ 'name' => 'Lorem Ipsum' ])
I am also using laravel framework but i used to do in that way :-
Layout :- resouces/views/layouts/app.blade.php
<html>
<head>
...
...
</head>
<body>
#include('layouts.navigation')
#yield('content') // use #yield here why you need separate file
#include('layouts.footer')
</body>
</html>
After that :- resouces/views/auth/login.blade.php
#extends('layouts.app')
#section('content')
<form>
// input
</form>
#stop
Hope it helps!.. I used to follow this structure in laravel project

BEM style layout of laravel view folder

I'm starting in on a Laravel project, and having come from past projects using BEM style folder layout (sort by block, not by type), I'd like to do the same within the views folder provided by Laravel. The benefits of having keeping these files together seem obvious, versus mirroring the folder structure in the js/sass folders, but there's some skepticism, prompting the question.
As an example, if I have a modal component, it would exist in:
views/components/modal
and it would consist of:
modal.blade.php
modal.scss
modal.js
So I'm wondering if there are any Laravel specific reasons why I wouldn't want to have a css & js file alongside an #component blade template.
Many people in the Laravel community are using a CRUD/MVC like structure.
Example for views.
views/users/index.blade.php
views/users/show.blade.php
views/users/create.blade.php
views/posts/index.blade.php
views/posts/show.blade.php
views/posts/create.blade.php
Routes (with corresponding methods)
Route::get('/users', 'UserController#index);
Route::get('/users', 'UserController#show);
Route::get('/users', 'UserController#create);
Route::get('/posts', 'PostController#index);
Route::get('/posts', 'PostController#show);
Route::get('/posts', 'PostController#create);
Method example
public function show(User $user)
{
return view('users.show', ['user' => $user]);
}
Blade example
<head>
<!-- Styles -->
<link href="{{ asset(css/posts.css) }}" rel="stylesheet">
</head>
<body>
<div id="app">
#yield('content')
</div>
<!-- Scripts -->
<script src="{{ asset('js/posts.js) }}"></script>
</body>

Calling dynamic components in Vue JS with laravel

I'm trying to build an application on Laravel 5.4 and Vue JS 2.0 I'm having a set of components which are being used in specific page only, right now I'm defining the components globally and using the components tag in blade file, as I said lot components are of no use, so my mix file is getting bigger and I think this might slow down my page rendering. I'm looking for a solution where I can call components dynamically in blade file. Following is my app.js file:
Vue.component('NavBar', require('./components/NavBar.vue'));
Vue.component('HomeBanner', require('./components/HomeBanner.vue'));
Vue.component('PageFooter', require('./components/Footer.vue'));
Vue.component('Categories', require('./components/Categories.vue'));
Vue.component('SubCategory', require('./components/SubCategory.vue'));
const app = new Vue({
el: '#app'
});
I've a master blade file which have following HTML codes:
<div id="app">
<nav-bar></nav-bar>
#yield('content')
<div class="clearfix"></div>
<page-footer></page-footer>
</div>
<!-- Core Scripts for Vue Components -->
<script src="{{ asset('js/app.js') }}"></script>
and suppose in index.blade.php I've
#extends('layouts.master')
#section('title', 'HomePage')
#section('content')
<home-banner></home-banner>
#endsection
and in categories page I'm having:
#extends('layouts.master')
#section('title', 'Select your category')
#section('content')
<categories></categories>
#endsection
any suggestion how to achieve this.
Try this:
Create a new file, say, partial.js at the same level of your app.js with this:
window.Vue = require('vue');
Vue.component('categories', require('./components/Categories.vue'));
new Vue({
el: '#testing'
});
Add the partial.js to the elixir webpack in gulpfile.js. Should look like this:
elixir(mix => {
mix.sass('app.scss')
.webpack('app.js')
.webpack('partial.js');
});
Then in the blade file you want to have this enclose the 'category' tag between a div with id='testing'
After that, import the partials.js script like this:
<script src="/js/partials.js"></script>
I believe the importing here has to be done AFTER using the category component.
Your categories page should end up like this:
#extends('layouts.master')
#section('title', 'Select your category')
#section('content')
<div id='testing'>
<categories></categories>
</div>
<script src="/js/partials.js"></script>
#endsection
Try it out and let me know, that's how I solved a similar problem in the past. Cheers!

How can I get Backbone router + Kendo UI Mobile (tabstrip) to work together?

How can I get Backbone router + Kendo UI Mobile (tabstrip) to work together?
I am just getting started with Backbone and have been looking at using it with a UI. I was able to do this with Backbone and jQuery Mobile (JQM) by disabling JQM's routing as outlined in this post: http://coenraets.org/blog/2012/03/using-backbone-js-with-jquery-mobile/
// Disable JQM routing
$(document).bind("mobileinit", function () {
$.mobile.ajaxEnabled = false;
$.mobile.linkBindingEnabled = false;
$.mobile.hashListeningEnabled = false;
$.mobile.pushStateEnabled = false;
});
// Backbone Router
// Create backbone view, append it to the body, and then use JQM to change to that page
home: function () {
page = new HomeView();
page.render();
$('body').append( $(page.el) );
$.mobile.changePage( $(page.el), {changeHash:false} );
}
Working through the Kendo UI Mobile docs, I have this working page:
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
<link href="http://cdn.kendostatic.com/2012.3.1315/styles/kendo.mobile.all.min.css" rel="stylesheet" />
</head>
<body>
<section data-role="layout" data-id="default">
<header data-role="header">
<div data-role="navbar">My App</div>
</header>
<!--View content will render here-->
<footer data-role="footer">
<div data-role="tabstrip">
<a class="tab-a" data-icon="home" href="#home">Home</a>
<a class="tab-a" data-icon="bookmarks" href="#about">About</a>
</div>
</footer>
</section>
<div data-role="view" data-layout="default" id="home">Home Page</div>
<div data-role="view" data-layout="default" id="about">About Page</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://cdn.kendostatic.com/2012.3.1315/js/kendo.all.min.js"></script>
<script>
var app = new kendo.mobile.Application();
</script>
</body>
</html>
It has a tabstrip with 2 buttons that enables you to switch between the 2 views.
I can get it to work with a Backbone router - whereby the routes "home" and "about" are called as the tabstrip buttons are clicked, but cannot work out how to intercept the click events, enabling me to generate a view, append it to the DOM, and then ensure that the relevant tabstrip button class is changed to represent the selected state.
I tried adding a class to the tabstrip links - $('.tabstrip-link').click( function () { alert( 'Clicked' ); } ) - but to no avail (sporadically fired). How can I remove the views from between the body tags, and generate these via a Backbone route, append them to the Layout between the header and footer sections, and then let the tabstrip change go about it's business?
You may need to disable the Kendo Router if you wish to use the Backbone router. The Kendo Router in mobile is not designed to be disabled. However at first glance, the following worked for me, if placed before creating your application.
kendo.mobile.Application.prototype._startHistory = function() {};
kendo.mobile.Application.prototype.router = {destroy: function() {}};
It works because Pane has it's own History management if the router is not created.

Resources