How do paths work in Vue.component() statement? - laravel

I am trying to learn Laravel and Vue properly, after an initial attempt back in the spring. I'm still pretty new to both though.
I am using Laravel 8.x in Windows 10 along with Vue 2.6.12. I am working my way through a video on combining Vue with Laravel. The video is for an older version of Laravel, probably 5.5, and probably a slightly older Vue as well so that may well be the nature of my problem. Here's the link to the video. I'm at about the 8:00 minute mark.
The problem I'm having is that when I try to execute my code, Laravel doesn't see my Articles component.
My app.js file is at /resources/assets/js/app.js. Here is the code:
require('./bootstrap');
window.Vue = required('vue');
Vue.component ('Articles', require('./components/Articles.vue'));
const app = new Vue({
el: '#app'
});
The file that contains the script tag is at /resources/views/welcome.blade.php. Here is the code:
<!doctype html>
<html lang="{{ 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">
<title>Larticles App</title>
<link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">
</head>
<body>
<div id="app">
<div class="container">
<Articles></Articles>
</div>
</div>
<script src="{{ asset('js/app.js') }}">console.log("Made it to here!");</script>
</body>
</html>
The Article component is at /resources/assets/js/components/Articles.vue. Here is the code:
<template>
<div>
<h2>Articles</h2>
</div>
</template>
<script>
export default {
name: "Articles",
beforeCreate() {
console.log("Articles - beforeCreate()");
},
created() {
console.log("Articles - created()");
},
beforeMount() {
console.log("Articles - beforeMount()");
},
mounted() {
console.log("Articles - mounted");
}
}
</script>
<style lang="scss" scoped>
#app {
background-color: gold;
color: blue;
}
</style>
What do I need to change to make this work? I think the issue is the require portion of the Vue.component statement in app.js but I've tried every variation I can think of without success. I can't think of anything else to try! I can't find anything in the Vue manual on special syntax for this statement in Vue or Laravel.
I should mention some things. I've deviated slightly from what he does in the video as part of my troubleshooting. I've capitalized Articles in the first parameter of the Vue.component statement and I've also capitalized it in the container div of the welcome.blade.php file. (Initially, I wrote it all lower case in each of those places but it didn't work that way either.) I've also added several console.log statements in the components lifecycle hooks and in the script tag. Absolutely none of them appear in the console though.
Also, for some reason, my IDE, VS Code, insists on displaying in red in the welcome.blade.php. Red always makes me think of errors but there is no error message of any kind. If I write those tags as (and change the app.js accordingly), they stay red so I don't think this is a casing issue.
I should also mention that the Inspector shows the as . Shouldn't it be showing exactly what I have in my welcome.blade.php file?

Use lower case letters when importing the component
<articles></articles>

Try to set each component you're reuire as default. Then use lower case as mentioned above. See below.
Vue.component ('Articles', require('./components/Articles.vue').default);
<articles></articles>

Related

Laravel - Vue component rendering twice because of app.js

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.

laravel does not load styles while passing value with urls

im using a laravel 5.4 and i have a problem with urls, when i send value with urls like http://localhost:8000/Music/{id} , laravel does not load styles but if use url without value to get that view it loads styles properly, it also does not load styles if an slash get added to end of url like http://localhost:8000/videos/ but without that slash http://localhost:8000/videos works without problem ..sorry i cant speak english good.
here is my code :
Route::get('Music/{id}','homeController#Music');
public function Music(music $item)
{
return view('music',['item'=>$item]);
}
this works by route model binding properly and does what i want but when it returns music blade file it does not load styles that i linked but if use this instead :
Route::get('Music','homeController#Music');
a
public function Music()
{
$item = music::find(1); //for example
return view('music',['item'=>$item]);
}
that works perfect.
i checked this many ways its because of {vlaues} in urls
it also does not loads styles or js files if an slash get added to end of urls
what is the problem?
Use the asset() function...
<html>
<head>
<link href="{{ asset('css/test.css') }}" rel="stylesheet">
</head>
<body>
<div class="square"></div>
<!-- Same for Javascript... -->
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
i tested it on this too
<html>
<head>
<link rel="stylesheet" href="css/test.css" type="text/css">
</head>
<body>
<div class="square"></div>
</body>
</html>

Polymer binding not working in Firefox

I'm seeing an issue where I can see the bound 'test' value appear on the demo page on Chrome but not in Firefox. I'm already including the polyfills (webcomponents-lite.js) so I'm really not sure what's missing. Any ideas?? Thank you in advance.
ticket-item demo page
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
<title>ticket-item demo</title>
<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="../../iron-demo-helpers/demo-pages-shared-styles.html">
<link rel="import" href="../../iron-demo-helpers/demo-snippet.html">
<link rel="import" href="../../iron-ajax/iron-ajax.html">
<link rel="import" href="../ticket-item.html">
<script>
window.addEventListener('WebComponentsReady', function() {
let element = document.getElementById('ticket-item');
element.test = 'test';
});
</script>
</head>
<body>
<div class="vertical-section-container centered">
<h3>Basic ticket-item demo</h3>
<demo-snippet>
<template>
<ticket-item id="ticket-item"></ticket-item>
</template>
</demo-snippet>
</div>
</body>
</html>
ticket-item element
<dom-module id="ticket-item">
<template>
<style include="my-theme">
:host {
display: block;
}
</style>
<div>test: [[test]]</div>
</template>
<script>
class TicketItem extends Polymer.Element {
static get is() { return 'TicketItem'; }
static get properties() {
return {
test: String
};
}
}
window.customElements.define(TicketItem.is, TicketItem);
</script>
</dom-module>
The first thing:
Custom element names. By specification, the custom element's name must start with a lower-case ASCII letter and must contain a dash (-). There's also a short list of prohibited element names that match existing names. For details, see the Custom elements core concepts section in the HTML specification.
So, you must change the name of "item" element.
Instead of loading the webcomponents-lite.js directly, load webcomponents-loader.js (a client-side loader that dynamically loads the minimum polyfill bundle, using feature detection), that will do the rest.
Plnkr link: works both in Firefox and Chrome.
The problem was that I named my component 'ticket-item' and the id was set to 'ticket-item'. It apparently needs to be something different from 'ticket-item'. I change the id to 'item' and now I'm seeing the binding.

Polymer elements don't work, when loaded by XHR

I'm trying to load a document with XHR, and move some loaded nodes into the main document. The problem is that Polymer elements defined in the loaded document "don't work" after moving. They are look and behave like regular <div>s.
Here is a simple repro case.
Loaded document:
<!-- insert.html -->
<div>
<link rel="import" href="paper-button/paper-button.html">
<div>Hello, world!</div>
<paper-button>I am a button</paper-button>
</div>
Main page:
<!-- index.html -->
<html>
<head>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="core-ajax/core-ajax.html">
<script>
window.addEventListener('polymer-ready', function() {
var ajax = document.getElementById('ajax');
ajax.addEventListener('core-response', function(e) {
var insertTo = document.getElementById('insertion-point');
insertTo.appendChild(e.detail.response.body.children[0]);
});
ajax.go();
});
</script>
</head>
<body>
<core-ajax id="ajax" url="insert.html" handleAs="document"></core-ajax>
<div id="insertion-point"> </div>
</body>
</html>
After loading I see that #insertion-point contains loaded document, as expected, but <paper-button> is not functioning and looks like <div>I am a button</div>.
Things don't get better when I add <link rel="import" href="paper-button/paper-button.html"> to the main page's <head>.
Replacing <core-ajax> with a native XMLHttpRequest doesn't help as well.
I'm testing on Google Chrome 42 with the latest Polymer.
My question: is this supposed to work at all? If not, why? If yes, who's to blame?
x-posting from Elliott Sprehn's response the polymer-dev mailing list.
This doesn't work because you're taking elements from an xhr document where there's no custom element registry and then just moving them. You need to do appendChild(document.importNode(response.body.children[0])) which will create a clone of the node, but using the document where polymer has registered the custom elements.

Converting working system to a chrome App

After hitting some of the limitations in a standard browser based application, I decided to convert it to a chrome App that doesn't use the browser.
Below are all the relevant parts. The problem I'm trying to solve is to add a load listener for a button that was working in the browser and doesn't work under the app architecture.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>POS Data Entry Sheet</title>
<link href="./POS.css" rel="stylesheet" type="text/css" />
<script src="./POS.js"></script>
<script src="./POS.underDevelopment.js"></script>
<script src="./POS.generateTable.js"></script>
<script src="./POS.menu.js"></script>
<script src="./POS.portion.js"></script>
<script src="./POS.formula.js"></script>
<script src="./POS.dialog.js"></script>
</head>
<body>
<script>
addLoadListener(addHandlerForLoginButton);
</script>
<section id="login">
<h1>Please login:</h1>
<p>
<label>User ID:</label><input type="text" id="userID">
<label>Password:</label><input type="password" id="password">
<button type="submit" id="loginButton">Login</button>
</p>
</section>
<div id="main"></div> <!--Everything gets attached to this div.-->
</body>
</html>
Everything above works via the browser.
I created the manifest:
{
"name": "Point of Sale System",
"description": "Dual currency Point of Sale System",
"version": "0.1",
"app": {
"background": {
"scripts": ["POS.dialog.js",
"POS.formula.js",
"POS.generateTable.js",
"POS.js",
"POS.menu.js",
"POS.portion.js",
"POS.underDevelopment.js",
"background.js"]
}
}
}
This is my first attempt at the background.js
It brings up the rudimentary page, but the in line script wasn't working.
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('POS.html', {
'bounds': {
'width': screen.availWidth,
'height': screen.availHeight
}
});
});
So, I commented out the inline script and attempted to add a callback function
This also doesn't work. No event listeners are recorded as per the debug tool.
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('POS.html', {
'bounds': {
'width': screen.availWidth,
'height': screen.availHeight
}
}, function(win) {win.addEventListener('load', addHandlerForLoginButton, false);});
});
I'm at a loss after several hours of attempting everything I could think of. Why doesn't the original in line script work, and why doesn't the callback work in the Chrome App architecture?
I think you are running into CSP problems, which does not allow inline script or script blocks. See http://developer.chrome.com/apps/contentSecurityPolicy.html for details.
You should be able to convert your first attempt by simply creating a page.js file, including it via a script src='page.js' tag, and put the contents of your script block in it:
addLoadListener(addHandlerForLoginButton);
Your second versoin didn't work because the win parameter to your callback isn't a DOM window but is an AppWindow. It has a DOM window attached via the contentWindow attribute, see http://developer.chrome.com/apps/app_window.html#type-AppWindow for details.
Lastly, you don't need to list all of those scripts in the app.background.scripts field of the manifest, only the background script background.js. The others will be loaded as needed when you open your page.

Resources