Vue 3 handling script tag inside root element - vue.js

I'm trying to avoid Vue from compiling script tag inside root element. Here is a code example:
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.5/vue.global.js"></script>
<script>const app = Vue.createApp({});</script>
<script type="application/javascript" src="global_component_bundled.js"></script>
<div id="app">
<script type="application/javascript" src="myJsFile.js"></script>
<global-component></global-component>
</div>
<script>app.mount("#app");</script>
</body>
I was trying to do something like this:
<script>app.config.isCustomElement = tag => tag.startsWith('script');</script>
but that doesn't work unfortunately for script tag.
The Problem is the warnings what i'm getting on browser console. Maybe is there any way to disable the warnings for script tag or to disable Vue from compiling this tag?
I know that i can do something like this:
<script>app.config.warnHandler = () => null;</script>
But i just want to disable this warning if is not possible vue to ignore compiling script tag:
Template compilation error: Tags with side effect (script and style) are ignored in client component templates.
But i prefer a way to ignore the script tag instead of disabling the warning.

I managed to get rid of the warning by using type="application/javascript" in all of the <script> tags.

Related

passing props to bundled vuejs project

I created a bundled myproject.min.js file using rollup, now I am using this in other frameworks(aurelia and angular).
Now my concern is how to pass data as props to this vue bundle from other frameworks:
in script file:
Vue.use(window.VueMainComponent);
new Vue({}).$mount('#app');
in HTML file:
<div id="app">
<vue-main-component :data="somedata"></vue-main-component>
</div>
I am trying above approach, but obviously getting the error somedata is not defined.
Okay I have figured this out, I made use of Vue.prototype.
in script file:
Vue.prototype.$somedata = {};
Vue.use(window.VueMainComponent);
new Vue({}).$mount('#app');
in HTML file:
<div id="app">
<vue-main-component :data="$somedata"></vue-main-component>
</div>

Using vue.js without NPM or CLI

I'd like to use Vue.js within one page of a large legacy application. The idea is to replace the old JS+jQuery hodge-podge within a single page -- but leave the rest of the app (many other pages) untouched. So, not interested in using NPM, Node, Vue CLI, Webpack, Babel, etc., just yet.
This is a proof-of-concept before we invest in refactoring the entire frontend of the application.
The approach we followed was to include vue.js via as explained here: https://v2.vuejs.org/v2/guide/installation.html#Direct-lt-script-gt-Include in that one page, and the use Vue only within that one page. This is the general page layout:
<html>
<head>
...
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
...
</head>
<body>
<div id="el">
... vue template ...
</div>
<script>
...
var vm = new Vue({
el : '#el',
data : {
config : <% config.json %> // this is server-rendered, using server templating
...
},
...
});
...
</script>
</body>
</html>
The page does work. However, I get the following error/warning within the Vue console:
Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as <script>, as they will not be parsed.
Although I'd rather not, I can certainly move the page-specific JS to its own separate file (and that does eliminate the warning/error). However, I wouldn't be able to set vm.config with server-provided data along with the loaded page by using server-side template, e.g. config : <% config.json %>. I know I could GET it using JS separately, after pageload, via an AJAX call directly from the server, but for practical reasons I'd like to avoid doing that here.
I'd greatly appreciate any suggestions on how to get this to work nicely. I'm also open to other suggestions with regard to this general pattern, that don't involve retooling the front-end just yet.
And perhaps the answer is to ignore the warning, or somehow disable it, given the page does work as intended...
Thank you!
One simple solution here is to write it to the global window object. IIRC SSR frameworks like Angular universal/Nuxt/Next/... all use this approach.
window.__STATE__ = <% config.json %>
In your JS file you can then refer to the window.__STATE__ object.
var vm = new Vue({
el: '#el',
data: {
config: window.__STATE__
}
})
Ofcourse the order is important here:
<body>
<script>
window.__STATE__ = <% config.json %>
</script>
<script src="app.js"></script>
</body>
Grrr, after several days after enduring this error, I discovered this:
<fieldset id="el">
...
<div id="el">
...
</div>
...
</fieldset>
So the issue was repeating #el within same page.
My mistake.
Just wish the error message emitted by Vue had been a bit more useful!
Bottom line: The pattern described in the origional question works just fine without NPM/CLI.

VueJS in Blade Template without Build Step

I'm trying to implement VueJS in one of my pages blade template. I just want to use Vue in that single template.
I tried the following:
default.blade.php
//...
#yield('js-for-layout-before')
<script src="{{ asset('js/vue.min.js') }}"></script>
// ...
view.blade.php
#extends('layouts.default')
//...
#section('content')
<div id="app">
<ol>
<todo-item></todo-item>
</ol>
<p>#{{ message }}</p>
</div>
<script type="module" src="{{ asset('js/pages/vue_component.js') }}"></script>
#stop
vue_component.js
Vue.component('todo-item', {
template: '<li>This is a list item</li>'
})
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
With this, I am only getting a blank page. There are no errors in the console, all files are loaded.
The inspector shows what I mean:
I do not want to implement a build step or anything, just a minimum setup with vue. Any ideas what I am missing here?
--UPDATE:
I replaced vue.min.js with the development version and finally got a clue:
vue.js:633 [Vue warn]: It seems you are using the standalone build of
Vue.js in an environment with Content Security Policy that prohibits
unsafe-eval. The template compiler cannot work in this environment.
Consider relaxing the policy to allow unsafe-eval or pre-compiling
your templates into render functions.
For reference, the issue was that my CSP didn't allow for unsafe-eval, which is required in this scenario without a build step. I didn't notice this until I included vue.js instead of the minified vue.min.js, which doesn't show errors.
To fix this for now, I did the following, though you should probably not do this in production: Check where your CSP is defined and add 'unsafe-eval' to "script-src".
In production, you probably want to use nonce on the script instead of unsafe-eval and something like https://github.com/spatie/laravel-csp to generate the nonce.

Creating Vue instance comments out everything

I'm trying to create an Chrome extension with web accessible resources. Since my extension tries to create a modal with a list of available data, I decided to use VueJS to handle the dynamic nature of content.
However, When I create the sample files and initialize VueJS, it simply leads to all the DOM being commented out and my app not working.
Here's the code I'm using:
web_resources/vue.html
<html>
<head>
<script type="text/javascript" src="/web_resources/vue.js"></script>
</head>
<body>
<div id="app">
{{ message }}
</div>
<script type="text/javascript" src="/web_resources/app.js"></script>
</body>
</html>
web_resources/app.js
window.app = new Vue({
el: '#app',
data: {
message: 'Hello World'
}
})
When I run this, the entire div is replaced with: <!----> and nothing works.
On searching online for VueJS inside iframe, I came across this post which has this fiddle which surprisingly produces a blank page for me with no content. On inspecting the result, I find that the div has been replaced with <!----> here as well.
Why is VueJS not initializing properly within an iframe?
The problem was Content Security Policy (CSP). Since I was using a local copy of vue.min.js, I couldn't see any of the error messages. It looked like everything was initializing as expected except it wasn't. Once I replaced this with a un-minified version, I saw an error on the lines of:
I simply had to go update the CSP in manifest.json which I was able to do by adding:
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",

$(...).tabs is not a function

I have this code on two pages on my site, but at one page the function doesn't work. Firebug shows me " $(...).tabs is not a function ". I don't understand why, can anyone tell me what is wrong ?
this is working:
http://www.invat-online.net/variante-rezolvate
this is not working:
http://www.invat-online.net/variante-explicate-limba-romana/varianta-01
Here is the code:
<div id="tabss">
<ul>
<li>Subiect I</li>
<li>Subiect II</li>
<li>Subiect III</li>
</ul>
<div id="SubiectI">content here</div>
<div id="SubiectII">content here</div>
<div id="SubiectIII">content here</div>
</div>
$(document).ready(function() {
$("#tabss").tabs();
});
You have relative paths to javascript files:
javascript/jquery-ui-1.9.2.custom.min.js
change them to absolute paths because you're using mod_rewrite module
/javascript/jquery-ui-1.9.2.custom.min.js
In first link the server is looking to the directory
http://www.invat-online.net/javascript/my_js_file.js (which exists)
but in the second one the path will be
http://www.invat-online.net/variante-explicate-limba-romana/javascript/my_js_file.js which do not exists
In my case:
I was using
jquery-ui-1.10.3.minimal.min.js
instead of
jquery-ui-1.10.3.custom.min.js
minimal version does not include ui.tabs.js, hence no ui.tabs function. Hope this helps someone else out there
The issue is that the jQuery UI js and css is not loading.
Try changing the path in you <script> tags to either the directory above ../javascript or the website root /javascript.
<script src="/javascript/head.min.js"></script>
<script src="/javascript/jquery-ui-1.9.2.custom.min.js"></script>
<link href="/stylesheets/smoothness/jquery-ui-1.9.2.custom.min.css" rel="stylesheet" />
Your first demo loads:
http://www.invat-online.net/javascript/jquery-ui-1.9.2.custom.min.js
Your second demo attempts to load:
http://www.invat-online.net/variante-explicate-limba-romana/javascript/jquery-ui-1.9.2.custom.min.js
The last one results in a 404. You should correct the path of the later, perhaps instructing it to find jQuery UI in one directory above the current: ../jquery-ui-1.9.2.custom.min.js.
Try this:
#section scripts{
$(document).ready(function() {
$("#tabss").tabs();
});
}
Put #Scripts.Render("~/bundles/jqueryui") in the <body></body> of your layout.cshtml
The error Uncaught TypeError: $(...).tabs is not a function may also be produced when in a Django project on the Admin area and using django-tabbed-admin under the following setup:
Django = 1.10.5
django-tabbed-admin=1.0.4
DEFAULT_JQUERY_UI_JS = 'tabbed_admin/js/jquery-ui-1.11.4.min.js'
The problem is that the code in jquery-ui-1.11.4.min.js for this Django lib is as follows:
/*! jQuery UI - v1.11.4 - 2015-07-27
(...)*/
jQuery = jQuery || django.jQuery.noConflict(false);
and the code on django-tabbed-admin uses it this way (change_form.html):
<script type="text/javascript">
(function($) {
$(window).scrollTop()
$('#tabs').tabs({
{% if add %}
// when adding, don't select a tab by default, we'll do it ourselves
// by finding the first available tab.
selected: -1
{% endif %}
});
(....)
})(django.jQuery);
</script>
<!-- end admin_tabs stuff -->
To sort this out this should be what would be passed in to the IIFE instead of the (django.jQuery) as above:
<script type="text/javascript">
(function($) {
(....)
})((typeof window.jQuery == 'undefined' && typeof window.django != 'undefined')
? django.jQuery
: jQuery)
</script>
<!-- end admin_tabs stuff -->
I've reported this issue in the project and created a PR with a fix for it. Waiting on it to be approved, so in the meantime you can sort it following my simple fix.
I hope this helps someone out there.
Check your page you might have loaded multiple versions of jQuery
I had the same problem, I realized that I had jquery and bootstrap css imports that enter in conflict each other. Take a look to the ones you have imported and reduce those imports to the minimum to see which is the conflict.
Here there is an example of how to implement it, I took that example and worked, then I adapted to my application:
for jquery 1.9 (click on view source to see the code)
http://jqueryui.com/tabs/
for jquery 1.8 (check the example at the end of the page)
http://api.jqueryui.com/1.8/tabs/
Hope it helps!