Multiple Vue instances bind to parent & child elements - javascript

I would like to ask for best setup of Vue instances (components), when I do not want use SPA.
My HTML looks like:
<html>
<div id="layout">
<div>Some Layout based content...</div>
<div id="homepage">
<simple-form-component></simple-form-component>
</div>
</div>
<script type=text/javascript src="homepage.js"></script>
<script type=text/javascript src="layout.js"></script>
</html>
Currently I have simple example ot two .js files:
layout.js
homepage.js
// layout.js
import Vue from 'vue/dist/vue.js'
new Vue({
el: '#layout',
});
// homepage.js
import Vue from 'vue/dist/vue.js';
import SimpleForm from '../../../../components/SimpleForm.vue';
new Vue({
el: '#homepage',
components: {
SimpleForm,
},
});
It seems to work fine, but I am suspicious that this is not 100% correct, due to console error:
[Vue warn]: Unknown custom element: - did you register
the component correctly? For recursive components, make sure to
provide the "name" option.
(found in )
Do you have any ideas/experience how to setup my scenario correctly?
PS: I would like to have my JS split into different files, managed by webpack and distributed by backend.
Thank you,
Mario

I've found workaround v-pre, my HTML will change the line: <div id="homepage" v-pre>. One small issue is, that I will not see my components in Vue Devtools.

Related

Vue.js showing blank page after init

My webpack entry file
import Vue from 'vue';
window.Vue = Vue;
Then my index.html
<div>
<div id="app">{{msg}} test</div>
</div>
<script>
console.log(window.Vue);
// This return a valid instance
window.addEventListener('load', () => {
new window.Vue({
el: '#app',
data: { msg: 'Hello World!' }
});
})
</script>
This loads, I briefly see {{msg}} test flash on the screen, and the Vue replaces the view. But its empty. {{msg}} doesnt display Hello World. But also "test" dissappears too, meaning it looks like the whole #app div gets replaced with empty content.
Whats happening here?
Strangest thing is if I include
<script src="main.js"></script>
<script src="https://unpkg.com/vue#2.1.10/dist/vue.js"></script>
Then it works. But if I dont include it console.log(window.Vue) still shows a valid instance??? So it should work?? Its getting passed correctly from my entry file.
Never seen this before. This is my first time using Vue.js outside of its normal cli context. Im trying to integrate it into an old legacy jQuery project.

Vue.js in Laravel

I am trying to use vue.js with laravel for the first time.
In the blade.php file:
<html>
<body class>
<div id="app">
<favourup></favourup>
</div>
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
In the app.js file:
Vue.component('favourup', require('./components/Favourup.vue'));
const app = new Vue({
el: '#app',
});
In the vue file:
<template>
<div>
<h2>FavourUp</h2>
</div>
</template>
I am not getting any errors however the local host displays an empty web page when it should display 'FavourUp'
you should write .default at end of require vue components because of part of the vue-loader 15 updates, if your code uses the CommonJS syntax for importing EcmaScript modules, you'll need to append .default:
https://laravel-mix.com/docs/4.0/upgrade#importing-es-modules
but as #Ifaruki said you can import it too here's the code:
// first
Vue.component('favourup', require('./components/Favourup.vue').default);
// second
import Favourup from './components/Favourup.vue';
Vue.component('favourup', Favourup);

Use Vue.js with ReactiveSearch in existing project

I have an existing web appliction that is not taking advantage of any existing reactive
frameworks or technology (like Angular, Vue or React).
I want use Vue.js with the ReactiveSearch opensource libary without rewriting my whole application.
While working through the tutorial (https://docs.appbase.io/docs/reactivesearch/vue/overview/QuickStart/) I encountered the following problem:
I can't use the components of the ReactiveSearch-Libary and I don't know why.
In my example I want create a multi-list component as described in the tutorial.
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#appbaseio/reactivesearch-vue#1.0.0-beta.19/dist/#appbaseio/reactivesearch-vue.umd.js"></script>
</head>
<body>
<div id="app">
<reactive-base app="good-books-ds" credentials="nY6NNTZZ6:27b76b9f-18ea-456c-bc5e-3a5263ebc63d">
<h1>Hello from ReactiveBase</h1>
<multi-list
componentId="Authors"
dataField="authors.raw"
class="filter"
title="Select Authors"
selectAllLabel="All Authors"
/>
</reactive-base>
</div>
<script>
import { ReactiveBase } from '#appbaseio/reactivesearch-vue';
Vue.config.productionTip = false;
Vue.use(ReactiveBase);
const vueApp = new Vue({
el: '#app'
})
</script>
</body>
</html>
I get following error message:
SyntaxError: import declarations may only appear at top level of a module

Load multiple components to js file but use only the required one(s)

I'm learning to use the svelte framework to make components. But I haven't been able to make an instance of only one component from those I have loaded into the js file.
So, this is my html file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script src="./build/ReviewPanelComponent.js"></script>
</body>
</html>
My js input file (where I import the components):
import ReviewPanel from './ReviewPanel.html';
const reviewPanel = new ReviewPanel({
target: document.querySelector( 'body' ),
data:
JSON.parse(localStorage.getItem('rooms'))
});
export default {
components: {
reviewPanel,
}
}
And the html for the component:
<style>
#main{
background-color:white;
}
h3,
h4,
h5{
font-weight: bold;
}
</style>
<div class="container">
<div class="row">
<div id="main" class="col-xs-12">
<div id="title">
{{#if BookedRooms.length > 0}}
{{#each BookedRooms as br}}
<h3>{{br.Title}}</h3>
{{#each br.PossibleRateTypes as prt}}
<h4>{{prt.UUID}}</h4>
{{/each}}
{{/each}}
{{/if}}
</div>
</div>
</div>
</div>
So, at this moment, it loads the component, because it has an instance on the js input file. The thing is, at this moment, if I want a second instance I have to create one of the js file itself. I was thinking more like just importing all the components I want in the js file and in the html file where I want to use them I would just call them.
Is this possible. I've been reading the docs but I haven't found what I want.
EDIT: I forgot to say that I'm using webpack, also. Hence the input and output files. I managed to use multiple components. The solution I've found was to just do this on my js input file:
import ReviewPanel from './ReviewPanel.html';
window.ReviewPanel=ReviewPanel;
window.ReviewPanel2=ReviewPanel;
I put the imported object in a global variable so I can call it where I want it, like so:
<div id="reviewPanel"></div>
<script type="text/javascript">
// Creates the review panel component
window.ReviewPanel = new ReviewPanel({
target: document.querySelector('#reviewPanel'),
data:
JSON.parse(localStorage.getItem('rooms'))
});
</script>
Yet, although I have this solution, my expectation would be import it only once in the js input file, without having to rely on global objects, and then just call it where I need it like so:
// And passing the parameters
<ReviewPanel />
Although I haven't seen much on React.js that's how I generally see programmers doing this. I was expecting the same. Still, as I have other things that need to be done, I'll leave it like this for now, to be optimized later.
Still, if anyone knows how to do this I'm all ears, as I'm new to Svelte and there's not much info on it, apart from the docs, which I consider a bit confusing on same parts.
If I understood correctly, to achieve your goal you could use a module bundler such as Rollup or webpack with their respective Svelte plugin and loader. In this perspective, the easiest way to start is to use a template based on one or the other.

VueJS components

I want to make use of VueJS components to clean up my scripts. Therefore I have a component for each page I am loading in into Laravel. Everything works fine so far. But I have issues transfering my current script logic to a component.
This is the current script setup importing the to be used components:
main.js
import HomeView from './components/HomeView.vue';
import IncidentView from './components/IncidentView.vue';
window.app = new Vue({
el: '.content',
components: {
HomeView, IncidentView
},
methods: {
// Init GIS
init: function() {
// Initialize GIS Map
initGISMap(this.$els.map);
},
}
(...)
}
Key for me is the window.app = new Vue... part. I make use of google maps and therefore when the page is loaded it searches for an app.init method. This is part of the script I am loading within the blade template:
<!DOCTYPE html>
<html>
<body class="hold-transition skin-blue sidebar-mini">
<section class="content-header">
<h1>
#yield('page_title')
<small>#yield('page_description')</small>
</h1>
</section>
<!-- Main content -->
<section class="content">
#if (isset($vueView))
<component is="{{ $vueView }}">
#endif
#yield('content')
</component>
</section>
<!-- /.content -->
<script src="https://maps.googleapis.com/maps/api/js?key=KEY&libraries=places&callback=app.init" async defer></script>
</body>
</html>
The individual pages (where I create for each a module in Vue) look like this:
#extends('app', ['vueView' => 'home-view'])
#section('page_title', 'title')
#section('page_description', 'title')
#section('content')
content
#endsection
By defining the vueView variable, the correct module I am importing in my script is used.
The goal is to use HomeView component as the main google maps view. And the other components for different pages I load when clicking the corresponding link in my theme. At the end, I do not want to have all VueJS code in one script. Therefore the models.
When I transfer all the content of this current JS file, I get an error complaining that app.init is not a function. The component looks like this:
<script>
export default {
data: {
// SEARCH
addressComponents: '',
autocompletePlace: '',
autocompleteAddress: '',
(...)
}
How do I modify my component in a way, that the app.init load would still work?
Someone has already mentioned GuillaumeLeclerc/vue-google-maps which is available on npm as vue-google-maps, but be warned that that version only works with vue 1.x
If you are using v2, look at this great vue2 fork xkjyeah/vue-google-maps - it's available as vue2-google-maps on npm.
The API is straightforward and doesn't diverge far from the v1 version, and the repository is much more active than its upsteam counterpart.
It really made my vue map work a lot more painless than rolling my own, which is what I was initially doing.
I hope that helps
Maybe you should use, or at least study the code, of a package that does that.
For example, you can check vue-google-maps on Github : https://github.com/GuillaumeLeclerc/vue-google-maps/
It defines a whole lot of Components related to Google Maps.
If I understand you right, you have a Google Maps script which, when loaded, calls window.app.init, right?
Does your Vue component have an init() method (none is shown above)? If there was one, it would need to be at app.methods.init() remember for VueJS, standard callable methods live under methods key.
Alternatively: you don't mention if your app.init is part of the Vue component or not. If its not it would appear that your app.init function is being overridden because you are redefining window.app as your vue component.
Lastly, if your init is part of Vue, is your google maps fn callback calling this init() before the Vue is loaded and therefore no such method exists (yet)?

Categories

Resources